Finishing Prototype

This commit is contained in:
Hoernschen 2020-10-17 12:07:39 +02:00
parent da9196f389
commit 473dc4a495
25 changed files with 1150 additions and 825 deletions

2
.vscode/launch.json vendored
View file

@ -9,7 +9,7 @@
"type": "go", "type": "go",
"request": "launch", "request": "launch",
"mode": "auto", "mode": "auto",
"program": "${workspaceFolder}/main.go", "program": "${workspaceFolder}/workloadGenerator.go",
"env": {}, "env": {},
"args": [] "args": []
} }

View file

@ -0,0 +1,11 @@
Iteration,Start,End
1,1602853607,1602853727
2,1602853727,1602853847
3,1602853847,1602853967
4,1602853967,1602854087
5,1602854087,1602854207
6,1602854207,1602854327
7,1602854327,1602854447
8,1602854447,1602854567
9,1602854567,1602854687
10,1602854687,1602854807
1 Iteration Start End
2 1 1602853607 1602853727
3 2 1602853727 1602853847
4 3 1602853847 1602853967
5 4 1602853967 1602854087
6 5 1602854087 1602854207
7 6 1602854207 1602854327
8 7 1602854327 1602854447
9 8 1602854447 1602854567
10 9 1602854567 1602854687
11 10 1602854687 1602854807

View file

@ -1,5 +1,11 @@
package config package config
import (
"time"
"github.com/lestrrat-go/backoff"
)
var ServerName string = "Hoernschen's Matrix Server" var ServerName string = "Hoernschen's Matrix Server"
var Version string = "0.1" var Version string = "0.1"
@ -11,11 +17,22 @@ var PublicKey []byte
var KeyId string var KeyId string
var VerifyKeys map[string]map[string][]byte var VerifyKeys map[string]map[string][]byte
// Parameters for Mesurements var Packetloss int
// TODO: Implement correctly var UnavailableTill int64
var Packetloss float32 var Consensus bool
var UnavailableTill int
var AuthentificationCheck bool var AuthentificationCheck bool
var Signing bool var Signing bool
var Encryption bool var Encryption bool
var HttpString string var HttpString string
var BackoffPolicy *backoff.Exponential
func SetDefaultParams() {
Packetloss = 0.0
UnavailableTill = time.Now().Unix()
Consensus = true
AuthentificationCheck = true
Signing = true
Encryption = true
HttpString = "https"
}

View file

@ -2,7 +2,6 @@ package device
import ( import (
"fmt" "fmt"
"log"
"git.nutfactory.org/hoernschen/Matrix/utils/database" "git.nutfactory.org/hoernschen/Matrix/utils/database"
) )
@ -26,6 +25,7 @@ func CreateDevice(device *Device, userId string) (err error) {
_, err = stmt.Exec(device.Id, device.Name, device.AccessToken, userId) _, err = stmt.Exec(device.Id, device.Name, device.AccessToken, userId)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
@ -60,7 +60,7 @@ func ReadDeviceFromAccessToken(accessToken string) (foundDevice *Device, err err
queryStmt := fmt.Sprintf(`SELECT id, name, accessToken queryStmt := fmt.Sprintf(`SELECT id, name, accessToken
FROM device FROM device
WHERE accessToken = '%s'`, accessToken) WHERE accessToken = '%s'`, accessToken)
log.Printf(queryStmt)
rows, err := database.DB.Query(queryStmt) rows, err := database.DB.Query(queryStmt)
if err != nil { if err != nil {
return return
@ -126,6 +126,7 @@ func UpdateDevice(device *Device) (err error) {
_, err = stmt.Exec(device.Name, device.AccessToken, device.Id) _, err = stmt.Exec(device.Name, device.AccessToken, device.Id)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -142,8 +143,9 @@ func DeleteDevice(id string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }

View file

@ -6,7 +6,7 @@ type Key struct {
Key []byte `json:"key,omitempty"` Key []byte `json:"key,omitempty"`
} }
type serverKeys struct { type ServerKeys struct {
ServerName string `json:"server_name,omitempty"` ServerName string `json:"server_name,omitempty"`
VerifyKeys map[string]verifyKey `json:"verify_keys,omitempty"` VerifyKeys map[string]verifyKey `json:"verify_keys,omitempty"`
OldVerifyKeys map[string]verifyKey `json:"old_verify_keys,omitempty"` OldVerifyKeys map[string]verifyKey `json:"old_verify_keys,omitempty"`

View file

@ -1,9 +1,12 @@
package device package device
import ( import (
"bytes"
"encoding/base64"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"time"
"git.nutfactory.org/hoernschen/Matrix/config" "git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/utils" "git.nutfactory.org/hoernschen/Matrix/utils"
@ -28,11 +31,11 @@ func GetServerSigningKeyHandler(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
response := serverKeys{ response := ServerKeys{
ServerName: config.Homeserver, ServerName: config.Homeserver,
VerifyKeys: make(map[string]verifyKey), VerifyKeys: make(map[string]verifyKey),
} }
response.VerifyKeys[config.KeyId] = verifyKey{Key: string(config.PublicKey)} response.VerifyKeys[config.KeyId] = verifyKey{Key: base64.RawStdEncoding.EncodeToString(config.PublicKey)}
content, err := json.Marshal(response) content, err := json.Marshal(response)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -50,26 +53,36 @@ func GetServerSigningKeyHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
// TODO: Use Function func GetVerifyKey(server string, id string) (key []byte, err error) {
func getVerifyKey(server string, id string) (key []byte, err error) {
if val, ok := config.VerifyKeys[server][id]; ok { if val, ok := config.VerifyKeys[server][id]; ok {
key = val key = val
} else { } else {
httpString := "https" requestUrl := fmt.Sprintf("%s://%s/_matrix/key/v2/server", config.HttpString, server)
requestUrl := fmt.Sprintf("%s://%s/_matrix/key/v2/server", httpString, server) client := &http.Client{Timeout: 2 * time.Second}
var res *http.Response var req *http.Request
res, err = http.Get(requestUrl) req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(nil))
if err != nil { if err != nil {
return return
} }
serverKeyRes := serverKeys{} var res *http.Response
res, err = client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
utils.HandleHTTPError(res)
}
serverKeyRes := ServerKeys{}
decoder := json.NewDecoder(res.Body) decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&serverKeyRes) err = decoder.Decode(&serverKeyRes)
config.VerifyKeys[server] = make(map[string][]byte) config.VerifyKeys[server] = make(map[string][]byte)
for keyId, verifyKey := range serverKeyRes.VerifyKeys { for keyId, verifyKey := range serverKeyRes.VerifyKeys {
config.VerifyKeys[server][keyId] = []byte(verifyKey.Key) verifyKeyBytes, err := base64.RawStdEncoding.DecodeString(verifyKey.Key)
if id == keyId { if err == nil {
key = []byte(verifyKey.Key) config.VerifyKeys[server][keyId] = verifyKeyBytes
if id == keyId {
key = verifyKeyBytes
}
} }
} }
} }

View file

@ -25,6 +25,7 @@ func CreateKey(key *Key, deviceId string) (err error) {
_, err = stmt.Exec(key.Id, key.Type, key.Key, deviceId) _, err = stmt.Exec(key.Id, key.Type, key.Key, deviceId)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
@ -99,6 +100,7 @@ func UpdateKey(key *Key) (err error) {
_, err = stmt.Exec(key.Type, key.Key, key.Id) _, err = stmt.Exec(key.Type, key.Key, key.Id)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -115,8 +117,9 @@ func DeleteKey(id string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }

View file

@ -86,7 +86,7 @@ type Notifications struct {
Room int `json:"room,omitempty"` Room int `json:"room,omitempty"`
} }
type sendMessageRequest struct { type SendMessageRequest struct {
MessageType string `json:"msgtype,omitempty"` MessageType string `json:"msgtype,omitempty"`
Body string `json:"body,omitempty"` Body string `json:"body,omitempty"`
} }

View file

@ -2,9 +2,12 @@ package event
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"log" "log"
"math/rand"
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
@ -13,8 +16,10 @@ import (
"git.nutfactory.org/hoernschen/Matrix/entities/device" "git.nutfactory.org/hoernschen/Matrix/entities/device"
"git.nutfactory.org/hoernschen/Matrix/entities/user" "git.nutfactory.org/hoernschen/Matrix/entities/user"
"git.nutfactory.org/hoernschen/Matrix/utils" "git.nutfactory.org/hoernschen/Matrix/utils"
"github.com/cenkalti/backoff/v4"
//"github.com/cenkalti/backoff/v4"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/lestrrat-go/backoff"
) )
func New( func New(
@ -85,7 +90,7 @@ func New(
func SendMessageHandler(w http.ResponseWriter, r *http.Request) { func SendMessageHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := sendMessageRequest{} request := SendMessageRequest{}
errResponse := utils.CheckRequest(r) errResponse := utils.CheckRequest(r)
if errResponse != nil { if errResponse != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -130,9 +135,7 @@ func SendMessageHandler(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
buf := new(bytes.Buffer) content, _ := json.Marshal(request)
buf.ReadFrom(r.Body)
content := buf.String()
err, newEvent := New( err, newEvent := New(
roomId, roomId,
foundUser.Id, foundUser.Id,
@ -140,7 +143,7 @@ func SendMessageHandler(w http.ResponseWriter, r *http.Request) {
time.Now().Unix(), time.Now().Unix(),
eventType, eventType,
foundUser.Id, foundUser.Id,
content, string(content),
txnId, txnId,
) )
if err != nil { if err != nil {
@ -173,13 +176,19 @@ func SendMessageHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
for _, server := range servers { for _, server := range servers {
operation := func() error { if server != config.Homeserver {
return SendTransaction(transaction, server) log.Printf("Send Transaction to %s", server)
/*
operation := func() error {
return SendTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
}
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
*/
go retryTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
} }
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
} }
response := createEventResponse{ response := createEventResponse{
EventId: newEvent.Id, EventId: newEvent.Id,
@ -190,6 +199,20 @@ func SendMessageHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
func retryTransaction(transactionToSend *Transaction, server string, httpString string, authCheck bool) (err error) {
b, cancel := config.BackoffPolicy.Start(context.Background())
defer cancel()
for backoff.Continue(b) {
err := SendTransaction(transactionToSend, server, httpString, authCheck)
if err == nil {
return nil
}
}
err = errors.New("Not able to send transaction")
return
}
func CreateStateEventHandler(w http.ResponseWriter, r *http.Request) { func CreateStateEventHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
errResponse := utils.CheckRequest(r) errResponse := utils.CheckRequest(r)
@ -271,13 +294,14 @@ func CreateStateEventHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
for _, server := range servers { for _, server := range servers {
operation := func() error { /*operation := func() error {
return SendTransaction(transaction, server) return SendTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
} }
notify := func(err error, duration time.Duration) { notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err) log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
} }
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify) go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)*/
go retryTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
} }
response := createEventResponse{ response := createEventResponse{
@ -405,106 +429,98 @@ func GetStateEventHandler(w http.ResponseWriter, r *http.Request) {
} }
func SyncEventsServerHandler(w http.ResponseWriter, r *http.Request) { func SyncEventsServerHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") packetLossNumber := rand.Intn(100)
request := syncEventsServerRequest{} if packetLossNumber > config.Packetloss {
errResponse := utils.CheckRequest(r) w.Header().Set("Content-Type", "application/json; charset=UTF-8")
if errResponse != nil { buf := new(bytes.Buffer)
w.WriteHeader(http.StatusBadRequest) buf.ReadFrom(r.Body)
if err := json.NewEncoder(w).Encode(errResponse); err != nil { request := syncEventsServerRequest{}
panic(err) errResponse := utils.CheckRequest(r)
} if errResponse != nil {
return w.WriteHeader(http.StatusBadRequest)
} if err := json.NewEncoder(w).Encode(errResponse); err != nil {
errResponse = utils.CheckAuthHeader(r) panic(err)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r)
txnId := vars["txnId"]
if txnId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
panic(err)
}
return
}
response := syncEventsServerResponse{
PDUs: make(map[string]pduProcessingResult),
}
missingEventIds := make(map[string][]string)
for _, pdu := range request.PDUs {
signatureValid := CheckSignature(*pdu)
if !signatureValid {
log.Printf("Wrong Signature for Event %s", pdu.Id)
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: "Signature not valid"}
continue
}
authEventsValid, err := CheckAuthEvents(pdu)
if !authEventsValid || err != nil {
log.Printf("Wrong Auth Events for Event %s", pdu.Id)
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Auth Check: %s", err)}
//continue
}
missingParentIds, err := CheckParents(pdu)
if len(missingParentIds) > 0 || err != nil {
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Parents Check: %s", err)}
for _, parentId := range missingParentIds {
missingEventIds[pdu.RoomId] = append(missingEventIds[pdu.RoomId], parentId)
} }
return
} }
foundEvent, err := ReadEvent(pdu.Id) _ = utils.CheckAuthHeader(r, buf.String())
if foundEvent == nil && err == nil { /*if errResponse != nil {
err = CreateEvent(pdu, txnId) w.WriteHeader(http.StatusBadRequest)
} if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}*/
err := json.Unmarshal(buf.Bytes(), &request)
if err != nil { if err != nil {
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Database Error: %s", err)} w.WriteHeader(http.StatusBadRequest)
continue if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("SyncEventsServerHandler Could not parse JSON Request: %s", err)}); err != nil {
} panic(err)
err = HandleEvent(pdu)
if err != nil {
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Event-Handling: %s", err)}
continue
}
response.PDUs[pdu.Id] = pduProcessingResult{}
}
if len(missingEventIds) > 0 {
for roomId, eventIds := range missingEventIds {
operation := func() error {
return Backfill(eventIds, roomId, request.Origin)
} }
notify := func(err error, duration time.Duration) { return
log.Printf("Error Backfill, retrying in %s: %s", duration/1000000000, err)
}
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
} }
} vars := mux.Vars(r)
txnId := vars["txnId"]
if txnId == "" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "SyncEventsServerHandler Missing Parameter"}); err != nil {
panic(err)
}
return
}
response := syncEventsServerResponse{
PDUs: make(map[string]pduProcessingResult),
}
missingEventIds := make(map[string][]string)
for _, pdu := range request.PDUs {
signatureValid := CheckSignature(*pdu)
if !signatureValid {
log.Printf("Wrong Signature for Event %s", pdu.Id)
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: "Signature not valid"}
//continue
}
authEventsValid, err := CheckAuthEvents(pdu)
if !authEventsValid || err != nil {
log.Printf("Wrong Auth Events for Event %s", pdu.Id)
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Auth Check: %s", err)}
//continue
}
missingParentIds, err := CheckParents(pdu)
if len(missingParentIds) > 0 || err != nil {
response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Parents Check: %s", err)}
for _, parentId := range missingParentIds {
missingEventIds[pdu.RoomId] = append(missingEventIds[pdu.RoomId], parentId)
}
}
w.WriteHeader(http.StatusOK) err = HandleEvent(pdu, txnId)
if err := json.NewEncoder(w).Encode(response); err != nil { if err != nil {
panic(err) response.PDUs[pdu.Id] = pduProcessingResult{ProcessingError: fmt.Sprintf("Error in Event-Handling: %s", err)}
continue
}
response.PDUs[pdu.Id] = pduProcessingResult{}
}
if len(missingEventIds) > 0 {
for roomId, eventIds := range missingEventIds {
Backfill(eventIds, roomId, request.Origin, config.HttpString, config.AuthentificationCheck)
}
}
w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil {
panic(err)
}
} else {
log.Println("Blocking Response")
} }
} }
func BackfillHandler(w http.ResponseWriter, r *http.Request) { func BackfillHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
errResponse := utils.CheckAuthHeader(r) errResponse := utils.CheckAuthHeader(r, "")
if errResponse != nil { if errResponse != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -526,7 +542,6 @@ func BackfillHandler(w http.ResponseWriter, r *http.Request) {
limit := 50 limit := 50
eventIds, ok := r.URL.Query()["v"] eventIds, ok := r.URL.Query()["v"]
log.Printf("%s", eventIds)
if !ok || eventIds[0] == "" { if !ok || eventIds[0] == "" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil {
@ -544,11 +559,7 @@ func BackfillHandler(w http.ResponseWriter, r *http.Request) {
for _, eventId := range eventIds { for _, eventId := range eventIds {
foundEvent, err := ReadEvent(eventId) foundEvent, err := ReadEvent(eventId)
if err != nil || foundEvent == nil { if err != nil || foundEvent == nil {
w.WriteHeader(http.StatusBadRequest) continue
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Event not found"}); err != nil {
panic(err)
}
return
} }
for newEventId, _ := range foundEvent.PrevEventHashes { for newEventId, _ := range foundEvent.PrevEventHashes {
@ -569,8 +580,8 @@ func BackfillHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
func SendTransaction(transaction *Transaction, homeserver string) (err error) { func SendTransaction(transaction *Transaction, homeserver string, httpString string, authentification bool) (err error) {
requestUrl := fmt.Sprintf("https://%s/_matrix/federation/v1/send/%s?", homeserver, transaction.Id) requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/send/%s?", httpString, homeserver, transaction.Id)
request := syncEventsServerRequest{ request := syncEventsServerRequest{
Origin: transaction.Origin, Origin: transaction.Origin,
Timestamp: transaction.Timestamp, Timestamp: transaction.Timestamp,
@ -580,24 +591,66 @@ func SendTransaction(transaction *Transaction, homeserver string) (err error) {
if err != nil { if err != nil {
return return
} }
client := &http.Client{} client := &http.Client{Timeout: 2 * time.Second}
req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody)) req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
if err != nil { if err != nil {
return return
} }
_, err = client.Do(req) if authentification {
var authHeader string
authHeader, err = utils.CreateAuthHeader(http.MethodPut, requestUrl, homeserver, string(reqBody))
if err != nil {
return
}
req.Header["Authorization"] = []string{authHeader}
}
req.Header["Content-Type"] = []string{"application/json"}
r, err := client.Do(req)
if err != nil {
return
}
if r.StatusCode != http.StatusOK {
utils.HandleHTTPError(r)
} else {
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
content := buf.String()
if content == "" {
err = errors.New("Missing Response")
return
}
}
return return
} }
func Backfill(eventIds []string, roomId string, homeserver string) (err error) { func Backfill(eventIds []string, roomId string, homeserver string, httpString string, authentification bool) (err error) {
requestUrl := fmt.Sprintf("https://%s/_matrix/federation/v1/backfill/%s?", homeserver, roomId) requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/backfill/%s?", httpString, homeserver, roomId)
for _, eventId := range eventIds { for _, eventId := range eventIds {
requestUrl = fmt.Sprintf("%sv=%s&", requestUrl, eventId) requestUrl = fmt.Sprintf("%sv=%s&", requestUrl, eventId)
} }
r, err := http.Get(requestUrl) client := &http.Client{Timeout: 2 * time.Second}
var req *http.Request
req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(nil))
if err != nil { if err != nil {
return return
} }
if authentification {
var authHeader string
authHeader, err = utils.CreateAuthHeader(http.MethodGet, requestUrl, homeserver, "")
if err != nil {
return
}
req.Header["Authorization"] = []string{authHeader}
}
req.Header["Content-Type"] = []string{"application/json"}
r, err := client.Do(req)
if err != nil {
return
}
if r.StatusCode != http.StatusOK {
errResponse := utils.HandleHTTPError(r)
log.Fatalf("%s (%s)", errResponse.ErrorMessage, errResponse.ErrorCode)
}
response := backfillResponse{} response := backfillResponse{}
defer r.Body.Close() defer r.Body.Close()
decoder := json.NewDecoder(r.Body) decoder := json.NewDecoder(r.Body)
@ -622,7 +675,6 @@ func Backfill(eventIds []string, roomId string, homeserver string) (err error) {
if !authEventsValid || err != nil { if !authEventsValid || err != nil {
log.Printf("Wrong Auth Events for Event %s", pdu.Id) log.Printf("Wrong Auth Events for Event %s", pdu.Id)
missingEventIds = append(missingEventIds, pdu.Id) missingEventIds = append(missingEventIds, pdu.Id)
continue
} }
missingParentIds, err := CheckParents(pdu) missingParentIds, err := CheckParents(pdu)
if len(missingParentIds) > 0 || err != nil { if len(missingParentIds) > 0 || err != nil {
@ -630,14 +682,8 @@ func Backfill(eventIds []string, roomId string, homeserver string) (err error) {
missingEventIds = append(missingEventIds, parentId) missingEventIds = append(missingEventIds, parentId)
} }
} }
foundEvent, err := ReadEvent(pdu.Id)
if foundEvent == nil && err == nil { err = HandleEvent(pdu, "")
err = CreateEvent(pdu, "")
}
if err != nil {
continue
}
err = HandleEvent(pdu)
if err != nil { if err != nil {
log.Printf("Error in Event-Handling: %s", err) log.Printf("Error in Event-Handling: %s", err)
continue continue
@ -645,7 +691,7 @@ func Backfill(eventIds []string, roomId string, homeserver string) (err error) {
} }
if len(missingEventIds) > 0 { if len(missingEventIds) > 0 {
Backfill(missingEventIds, roomId, homeserver) Backfill(missingEventIds, roomId, homeserver, config.HttpString, config.AuthentificationCheck)
} }
return return
@ -656,6 +702,9 @@ func generateEventId(id string) string {
} }
func GetAuthChain(newEvent *Event) (authChain []*Event, err error) { func GetAuthChain(newEvent *Event) (authChain []*Event, err error) {
if !config.AuthentificationCheck {
return
}
createEvent, err := ReadStateEvent(newEvent.RoomId, "m.room.create", "") createEvent, err := ReadStateEvent(newEvent.RoomId, "m.room.create", "")
if err != nil { if err != nil {
return return
@ -698,7 +747,6 @@ func GetAuthChain(newEvent *Event) (authChain []*Event, err error) {
func GetAuthEvents(newEvent *Event) (authEventHashes map[string]EventHash, err error) { func GetAuthEvents(newEvent *Event) (authEventHashes map[string]EventHash, err error) {
authEventHashes = make(map[string]EventHash) authEventHashes = make(map[string]EventHash)
authChain, err := GetAuthChain(newEvent) authChain, err := GetAuthChain(newEvent)
if err != nil { if err != nil {
return return
@ -730,10 +778,12 @@ func CheckEventHash(id string, hash EventHash) (correct bool, eventFound bool, e
} }
func CheckParents(eventToCheck *Event) (missingParentIds []string, err error) { func CheckParents(eventToCheck *Event) (missingParentIds []string, err error) {
for key, hash := range eventToCheck.PrevEventHashes { if config.Consensus {
correctHash, foundEvent, err := CheckEventHash(key, hash) for key, hash := range eventToCheck.PrevEventHashes {
if !correctHash || !foundEvent || err != nil { correctHash, foundEvent, err := CheckEventHash(key, hash)
missingParentIds = append(missingParentIds, key) if !correctHash || !foundEvent || err != nil {
missingParentIds = append(missingParentIds, key)
}
} }
} }
return return
@ -741,13 +791,16 @@ func CheckParents(eventToCheck *Event) (missingParentIds []string, err error) {
func CheckAuthEvents(eventToCheck *Event) (correct bool, err error) { func CheckAuthEvents(eventToCheck *Event) (correct bool, err error) {
correct = true correct = true
if !config.AuthentificationCheck {
return
}
authEvents, err := GetAuthEvents(eventToCheck) authEvents, err := GetAuthEvents(eventToCheck)
if err != nil { if err != nil {
return return
} }
for key, hash := range authEvents { for key, hash := range authEvents {
if eventToCheck.AuthEventHashes[key].SHA256 != hash.SHA256 { if eventToCheck.AuthEventHashes[key].SHA256 != hash.SHA256 {
correct = false //correct = false
return return
} }
} }
@ -755,6 +808,10 @@ func CheckAuthEvents(eventToCheck *Event) (correct bool, err error) {
} }
func CheckSignature(eventToCheck Event) (correct bool) { func CheckSignature(eventToCheck Event) (correct bool) {
if !config.Signing {
correct = true
return
}
correct = false correct = false
signatures := eventToCheck.Signatures signatures := eventToCheck.Signatures
eventToCheck.Unsigned = UnsignedData{} eventToCheck.Unsigned = UnsignedData{}
@ -763,32 +820,33 @@ func CheckSignature(eventToCheck Event) (correct bool) {
if err != nil { if err != nil {
return return
} }
for id, signature := range signatures[eventToCheck.Sender] { for id, signature := range signatures[eventToCheck.Origin] {
key, err := device.ReadKey(id) verifyKey, err := device.GetVerifyKey(eventToCheck.Origin, id)
if err == nil { if err == nil && verifyKey != nil {
correct = utils.VerifySignature([]byte(key.Key), jsonString, []byte(signature)) correct = utils.VerifySignature(verifyKey, jsonString, signature)
} }
} }
return return
} }
func HandleEvents(events []*Event) (err error) { func HandleEvents(events []*Event, txnId string) (err error) {
for _, eventToHandle := range events { for _, eventToHandle := range events {
err = HandleEvent(eventToHandle) err = HandleEvent(eventToHandle, txnId)
} }
return return
} }
func HandleEvent(eventToHandle *Event) (err error) { func HandleEvent(eventToHandle *Event, txnId string) (err error) {
log.Printf("EventType: %s", eventToHandle.EventType)
foundEvent, err := ReadEvent(eventToHandle.Id)
if foundEvent == nil && err == nil {
err = CreateEvent(eventToHandle, txnId)
}
if err != nil {
return
}
if eventToHandle.EventType == "m.room.message" { if eventToHandle.EventType == "m.room.message" {
message := sendMessageRequest{} log.Printf("%s: %s", eventToHandle.Sender, eventToHandle.Content)
err = json.Unmarshal([]byte(eventToHandle.Content), &message)
if err != nil {
return
}
if message.MessageType != "" && message.MessageType == "m.text" {
log.Printf("%s: %s", eventToHandle.Sender, message.Body)
}
} else if eventToHandle.EventType == "m.room.member" { } else if eventToHandle.EventType == "m.room.member" {
message := MemberEventContent{} message := MemberEventContent{}
err = json.Unmarshal([]byte(eventToHandle.Content), &message) err = json.Unmarshal([]byte(eventToHandle.Content), &message)
@ -796,7 +854,11 @@ func HandleEvent(eventToHandle *Event) (err error) {
return return
} }
if message.Membership == "join" { if message.Membership == "join" {
CreateRoomMember(eventToHandle.RoomId, eventToHandle.StateKey) log.Printf("Join %s to Room %s", eventToHandle.StateKey, eventToHandle.RoomId)
}
err = CreateRoomMember(eventToHandle.RoomId, eventToHandle.StateKey, eventToHandle.Origin)
if err != nil {
return
} }
} }
return return

View file

@ -2,12 +2,11 @@ package event
import ( import (
"fmt" "fmt"
"strings"
"git.nutfactory.org/hoernschen/Matrix/utils/database" "git.nutfactory.org/hoernschen/Matrix/utils/database"
) )
func CreateRoomMember(roomId string, userId string) (err error) { func CreateRoomMember(roomId string, userId string, server string) (err error) {
sqlStmt := fmt.Sprintf(`INSERT INTO roomMember sqlStmt := fmt.Sprintf(`INSERT INTO roomMember
(roomId, userId, server) (roomId, userId, server)
VALUES VALUES
@ -24,8 +23,9 @@ func CreateRoomMember(roomId string, userId string) (err error) {
} }
defer stmt.Close() defer stmt.Close()
_, err = stmt.Exec(roomId, userId, strings.Split(userId, ":")[1]) _, err = stmt.Exec(roomId, userId, server)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
@ -55,6 +55,7 @@ func CreateParents(eventId string, parentIds map[string]EventHash) (err error) {
parentId, parentId,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
} }
@ -87,6 +88,7 @@ func CreateAuthEvents(eventId string, authEventIds map[string]EventHash) (err er
authEventId, authEventId,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
} }
@ -133,6 +135,7 @@ func CreateEvent(event *Event, txnId string) (err error) {
signatures, signatures,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
@ -188,6 +191,7 @@ func CreateEventsFromTransaction(txnId string, pdus map[string]*Event) (err erro
signatures, signatures,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -385,7 +389,7 @@ func ReadAuthEvents(eventId string) (authEvents map[string]EventHash, err error)
} }
func ReadEvent(id string) (foundEvent *Event, err error) { func ReadEvent(id string) (foundEvent *Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE id = '%s'`, id) WHERE id = '%s'`, id)
@ -406,6 +410,7 @@ func ReadEvent(id string) (foundEvent *Event, err error) {
&foundEvent.Origin, &foundEvent.Origin,
&foundEvent.Timestamp, &foundEvent.Timestamp,
&foundEvent.EventType, &foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content, &foundEvent.Content,
&foundEvent.Depth, &foundEvent.Depth,
&foundEvent.Hashes.SHA256, &foundEvent.Hashes.SHA256,
@ -435,14 +440,14 @@ func ReadEvent(id string) (foundEvent *Event, err error) {
} }
func ReadStateEvent(roomId string, eventType string, stateKey string) (foundEvent *Event, err error) { func ReadStateEvent(roomId string, eventType string, stateKey string) (foundEvent *Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE roomId = '%s' WHERE roomId = '%s'
AND eventType = '%s' AND eventType = '%s'
AND stateKey = '%s'`, roomId, eventType, stateKey) AND stateKey = '%s'`, roomId, eventType, stateKey)
if stateKey == "" { if stateKey == "" {
queryStmt = fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt = fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE roomId = '%s' WHERE roomId = '%s'
AND eventType = '%s'`, roomId, eventType) AND eventType = '%s'`, roomId, eventType)
@ -465,6 +470,7 @@ func ReadStateEvent(roomId string, eventType string, stateKey string) (foundEven
&foundEvent.Origin, &foundEvent.Origin,
&foundEvent.Timestamp, &foundEvent.Timestamp,
&foundEvent.EventType, &foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content, &foundEvent.Content,
&foundEvent.Depth, &foundEvent.Depth,
&foundEvent.Hashes.SHA256, &foundEvent.Hashes.SHA256,
@ -494,7 +500,7 @@ func ReadStateEvent(roomId string, eventType string, stateKey string) (foundEven
} }
func ReadStateEvents(roomId string, eventType string) (foundEvents []*Event, err error) { func ReadStateEvents(roomId string, eventType string) (foundEvents []*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE roomId = '%s' WHERE roomId = '%s'
AND eventType = '%s'`, roomId, eventType) AND eventType = '%s'`, roomId, eventType)
@ -516,6 +522,7 @@ func ReadStateEvents(roomId string, eventType string) (foundEvents []*Event, err
&foundEvent.Origin, &foundEvent.Origin,
&foundEvent.Timestamp, &foundEvent.Timestamp,
&foundEvent.EventType, &foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content, &foundEvent.Content,
&foundEvent.Depth, &foundEvent.Depth,
&foundEvent.Hashes.SHA256, &foundEvent.Hashes.SHA256,
@ -547,7 +554,7 @@ func ReadStateEvents(roomId string, eventType string) (foundEvents []*Event, err
} }
func ReadEventsFromRoom(roomId string) (events map[string]*Event, err error) { func ReadEventsFromRoom(roomId string) (events map[string]*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE roomId = '%s'`, roomId) WHERE roomId = '%s'`, roomId)
@ -570,6 +577,7 @@ func ReadEventsFromRoom(roomId string) (events map[string]*Event, err error) {
&foundEvent.Origin, &foundEvent.Origin,
&foundEvent.Timestamp, &foundEvent.Timestamp,
&foundEvent.EventType, &foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content, &foundEvent.Content,
&foundEvent.Depth, &foundEvent.Depth,
&foundEvent.Hashes.SHA256, &foundEvent.Hashes.SHA256,
@ -601,7 +609,7 @@ func ReadEventsFromRoom(roomId string) (events map[string]*Event, err error) {
} }
func ReadStateEventsFromRoom(roomId string) (events []*Event, err error) { func ReadStateEventsFromRoom(roomId string) (events []*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE eventType <> 'm.room.message' AND roomId = '%s'`, roomId) WHERE eventType <> 'm.room.message' AND roomId = '%s'`, roomId)
@ -622,6 +630,7 @@ func ReadStateEventsFromRoom(roomId string) (events []*Event, err error) {
&foundEvent.Origin, &foundEvent.Origin,
&foundEvent.Timestamp, &foundEvent.Timestamp,
&foundEvent.EventType, &foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content, &foundEvent.Content,
&foundEvent.Depth, &foundEvent.Depth,
&foundEvent.Hashes.SHA256, &foundEvent.Hashes.SHA256,
@ -653,7 +662,7 @@ func ReadStateEventsFromRoom(roomId string) (events []*Event, err error) {
} }
func ReadEventsFromTransaction(txnId string) (events []*Event, err error) { func ReadEventsFromTransaction(txnId string) (events []*Event, err error) {
queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, content, depth, hash, signature queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature
FROM event FROM event
WHERE txnId = '%s'`, txnId) WHERE txnId = '%s'`, txnId)
@ -674,6 +683,7 @@ func ReadEventsFromTransaction(txnId string) (events []*Event, err error) {
&foundEvent.Origin, &foundEvent.Origin,
&foundEvent.Timestamp, &foundEvent.Timestamp,
&foundEvent.EventType, &foundEvent.EventType,
&foundEvent.StateKey,
&foundEvent.Content, &foundEvent.Content,
&foundEvent.Depth, &foundEvent.Depth,
&foundEvent.Hashes.SHA256, &foundEvent.Hashes.SHA256,
@ -727,6 +737,7 @@ func UpdateEvent(event *Event) (err error) {
event.Id, event.Id,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -743,8 +754,9 @@ func DeleteEvent(id string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -771,8 +783,9 @@ func DeleteParents(eventId string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -789,8 +802,9 @@ func DeleteAuthEvents(eventId string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }

View file

@ -25,6 +25,7 @@ func CreateTransaction(transaction *Transaction) (err error) {
_, err = stmt.Exec(transaction.Id, transaction.Origin, transaction.Timestamp) _, err = stmt.Exec(transaction.Id, transaction.Origin, transaction.Timestamp)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
@ -74,6 +75,7 @@ func UpdateTransaction(transaction *Transaction) (err error) {
_, err = stmt.Exec(transaction.Origin, transaction.Timestamp, transaction.Id) _, err = stmt.Exec(transaction.Origin, transaction.Timestamp, transaction.Id)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -90,8 +92,9 @@ func DeleteTransaction(id string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }

View file

@ -6,6 +6,7 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"time"
"git.nutfactory.org/hoernschen/Matrix/config" "git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/entities/device" "git.nutfactory.org/hoernschen/Matrix/entities/device"
@ -26,12 +27,13 @@ type serverImplementation struct {
Version string `json:"version,omitempty"` Version string `json:"version,omitempty"`
} }
type ResetBody struct { type SetParamBody struct {
Packetloss float32 `json:"packetloss,omitempty"` Packetloss int `json:"packetloss,omitempty"`
UnavailableTill int `json:"unavailableTill,omitempty"` UnavailableTill int64 `json:"unavailableTill,omitempty"`
AuthentificationCheck bool `json:"authentificationCheck,omitempty"` Consensus bool `json:"consensus,omitempty"`
Signing bool `json:"signing,omitempty"` AuthentificationCheck bool `json:"authentificationCheck,omitempty"`
Encryption bool `json:"encryption,omitempty"` Signing bool `json:"signing,omitempty"`
Encryption bool `json:"encryption,omitempty"`
} }
func ResolveServerName(w http.ResponseWriter, r *http.Request) { func ResolveServerName(w http.ResponseWriter, r *http.Request) {
@ -52,10 +54,9 @@ func GetServerImplementation(w http.ResponseWriter, r *http.Request) {
} }
} }
// TODO: Add a function to set the Config-Params func SetParams(w http.ResponseWriter, r *http.Request) {
func Reset(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := ResetBody{} request := SetParamBody{}
errResponse := utils.CheckRequest(r) errResponse := utils.CheckRequest(r)
if errResponse != nil { if errResponse != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -74,22 +75,45 @@ func Reset(w http.ResponseWriter, r *http.Request) {
return return
} }
config.Packetloss = request.Packetloss
config.UnavailableTill = request.UnavailableTill
config.Consensus = request.Consensus
config.AuthentificationCheck = request.AuthentificationCheck
config.Signing = request.Signing
config.Encryption = request.Signing
config.HttpString = "https"
if !config.Encryption {
config.HttpString = "http"
}
w.WriteHeader(http.StatusOK)
}
func Reset(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
if err := device.InitServerSigningKey(); err != nil { if err := device.InitServerSigningKey(); err != nil {
log.Fatal(err) log.Fatal(err)
} }
config.VerifyKeys = make(map[string]map[string][]byte) config.VerifyKeys = make(map[string]map[string][]byte)
os.Remove("sqlite.db") if err := os.Remove("sqlite.db"); err != nil {
log.Println(err)
}
if err := database.InitDB("sqlite.db"); err != nil { if err := database.InitDB(fmt.Sprintf("sqlite%s.db", time.Now().Unix())); err != nil {
log.Fatal(err) log.Fatal(err)
} }
config.Packetloss = request.Packetloss config.SetDefaultParams()
config.UnavailableTill = request.UnavailableTill
config.AuthentificationCheck = request.AuthentificationCheck
config.Signing = request.Signing
config.Encryption = request.Signing
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }

View file

@ -34,8 +34,6 @@ type CreateRoomResponse struct {
RoomId string `json:"room_id,omitempty"` RoomId string `json:"room_id,omitempty"`
} }
type getRoomMemberRequest struct{}
type getRoomMemberResponse struct { type getRoomMemberResponse struct {
Chunk []*event.Event `json:"chunk,omitempty"` Chunk []*event.Event `json:"chunk,omitempty"`
} }
@ -48,12 +46,6 @@ type JoinRoomUserResponse struct {
RoomId string `json:"room_id,omitempty"` RoomId string `json:"room_id,omitempty"`
} }
type leaveRoomUserRequest struct{}
type leaveRoomUserResponse struct{}
type makeJoinRequest struct{}
type makeJoinResponse struct { type makeJoinResponse struct {
RoomVersion string `json:"room_version,omitempty"` RoomVersion string `json:"room_version,omitempty"`
Event event.Event `json:"event,omitempty"` Event event.Event `json:"event,omitempty"`
@ -74,14 +66,6 @@ type joinRoomServerResponse struct {
State []*event.Event `json:"state,omitempty"` State []*event.Event `json:"state,omitempty"`
} }
type makeLeaveRequest struct{}
type makeLeaveResponse struct{}
type leaveRoomServerRequest struct{}
type leaveRoomServerResponse struct{}
type invite3pid struct { type invite3pid struct {
IdServer string `json:"id_server,omitempty"` IdServer string `json:"id_server,omitempty"`
IdAccessToken string `json:"id_access_token,omitempty"` IdAccessToken string `json:"id_access_token,omitempty"`
@ -105,10 +89,8 @@ type invite struct {
} }
type thirdPartySigned struct { type thirdPartySigned struct {
Sender string `json:"sender,omitempty"` Sender string `json:"sender,omitempty"`
MXID string `json:"mxid,omitempty"` MXID string `json:"mxid,omitempty"`
Signatures signatures `json:"signatures,omitempty"` Signatures map[string]map[string]string `json:"signatures,omitempty"`
Token string `json:"token,omitempty"` Token string `json:"token,omitempty"`
} }
type signatures struct{}

View file

@ -324,7 +324,6 @@ func CreateRoomHandler(w http.ResponseWriter, r *http.Request) {
func GetRoomMemberHandler(w http.ResponseWriter, r *http.Request) { func GetRoomMemberHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := getRoomMemberRequest{}
errResponse := utils.CheckRequest(r) errResponse := utils.CheckRequest(r)
if errResponse != nil { if errResponse != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -349,16 +348,6 @@ func GetRoomMemberHandler(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r) vars := mux.Vars(r)
roomId := vars["roomId"] roomId := vars["roomId"]
if roomId == "" { if roomId == "" {
@ -407,7 +396,7 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
err = decoder.Decode(&request) err = decoder.Decode(&request)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Could not parse JSON Request: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -416,7 +405,7 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
roomId := vars["roomId"] roomId := vars["roomId"]
if roomId == "" { if roomId == "" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "JoinRoomUserHandler Missing Parameter"}); err != nil {
panic(err) panic(err)
} }
return return
@ -424,49 +413,46 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
foundRoom, err := ReadRoom(roomId) foundRoom, err := ReadRoom(roomId)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Database Error ReadRoom: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
var joinEvent *event.Event var joinEvent *event.Event
if foundRoom == nil { if foundRoom == nil {
memberEventContent := event.MemberEventContent{ server := strings.Split(roomId, ":")[1]
DisplayName: foundUser.Name, requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/make_join/%s/%s", config.HttpString, server, roomId, foundUser.Id)
IsDirect: true, client := &http.Client{Timeout: 2 * time.Second}
Membership: "join", var req *http.Request
} req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(nil))
memberEventContentBytes, _ := json.Marshal(memberEventContent) if err != nil {
err, memberEvent := event.New( return
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(memberEvent, "")
} }
req.Header["Content-Type"] = []string{"application/json"}
res, err := client.Do(req)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Error Getting Response Make JSON: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
httpString := "https" if res.StatusCode != http.StatusOK {
server := strings.Split(roomId, ":")[1] errResponse = utils.HandleHTTPError(res)
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/make_join/%s/%s", httpString, server, roomId, foundUser.Id) if errResponse != nil {
res, err := http.Get(requestUrl) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
}
makeJoinRes := makeJoinResponse{} makeJoinRes := makeJoinResponse{}
decoder = json.NewDecoder(res.Body) decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&makeJoinRes) err = decoder.Decode(&makeJoinRes)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Could not parse JSON makeJoinResponse: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -474,7 +460,7 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
err = CreateRoom(&Room{Id: roomId, Version: makeJoinRes.RoomVersion}) err = CreateRoom(&Room{Id: roomId, Version: makeJoinRes.RoomVersion})
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Database Error CreateRoom: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -489,62 +475,80 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
makeJoinRes.Event.Content, makeJoinRes.Event.Content,
"", "",
) )
requestUrl = fmt.Sprintf("%s://%s/_matrix/federation/v2/send_join/%s/%s", httpString, server, roomId, joinEvent.Id) requestUrl = fmt.Sprintf("%s://%s/_matrix/federation/v2/send_join/%s/%s", config.HttpString, server, roomId, joinEvent.Id)
reqBody, err := json.Marshal(joinEvent) reqBody, err := json.Marshal(joinEvent)
if err != nil { if err != nil {
return return
} }
client := &http.Client{} client = &http.Client{Timeout: 2 * time.Second}
req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody)) req, err = http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
if err != nil { if err != nil {
return return
} }
req.Header["Content-Type"] = []string{"application/json"}
res, err = client.Do(req) res, err = client.Do(req)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Error Getting Response Send Join: %s", err)}); err != nil {
panic(err)
}
return
}
if res.StatusCode != http.StatusOK {
errResponse = utils.HandleHTTPError(res)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(errResponse); err != nil {
panic(err)
}
return
}
}
joinRes := joinRoomServerResponse{} joinRes := joinRoomServerResponse{}
decoder = json.NewDecoder(res.Body) decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&joinRes) err = decoder.Decode(&joinRes)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Could not parse JSON joinRoomServerResponse: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
err = event.HandleEvents(joinRes.State) err = event.HandleEvents(joinRes.State, "")
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Handling Events: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Error Handling Events: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
} else {
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: true,
Membership: "join",
}
memberEventContentBytes, _ := json.Marshal(memberEventContent)
err, joinEvent = event.New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
} }
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: true,
Membership: "join",
}
memberEventContentBytes, _ := json.Marshal(memberEventContent)
err, joinEvent = event.New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
err, txnId := utils.CreateUUID() err, txnId := utils.CreateUUID()
err = event.CreateEvent(joinEvent, txnId) err = event.CreateEvent(joinEvent, txnId)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Database Error CreateEvent: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
event.HandleEvent(joinEvent, "")
transaction := &event.Transaction{ transaction := &event.Transaction{
Id: txnId, Id: txnId,
Origin: config.Homeserver, Origin: config.Homeserver,
@ -554,30 +558,33 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
servers, err := event.ReadServers(roomId) servers, err := event.ReadServers(roomId)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Database Error ReadServers: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
for _, server := range servers { for _, server := range servers {
//if server != config.Homeserver { if server != config.Homeserver {
operation := func() error { log.Printf("Send Transaction to %s", server)
return event.SendTransaction(transaction, server) operation := func() error {
return event.SendTransaction(transaction, server, config.HttpString, config.AuthentificationCheck)
}
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
} }
notify := func(err error, duration time.Duration) {
log.Printf("Error Sending Transaction, retrying in %ss: %s", duration/1000000000, err)
}
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
//}
} }
err = CreateRoomMember(roomId, foundUser.Id) /*
if err != nil { err = CreateRoomMember(roomId, foundUser.Id, config.Homeserver)
w.WriteHeader(http.StatusBadRequest) if err != nil {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil { w.WriteHeader(http.StatusBadRequest)
panic(err) if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Database Error CreateRoomMember: %s", err)}); err != nil {
panic(err)
}
return
} }
return */
}
response := JoinRoomUserResponse{RoomId: roomId} response := JoinRoomUserResponse{RoomId: roomId}
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
if err := json.NewEncoder(w).Encode(response); err != nil { if err := json.NewEncoder(w).Encode(response); err != nil {
@ -587,7 +594,6 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) { func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := makeJoinRequest{}
errResponse := utils.CheckRequest(r) errResponse := utils.CheckRequest(r)
if errResponse != nil { if errResponse != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
@ -596,21 +602,12 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
} }
return return
} }
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&request)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil {
panic(err)
}
return
}
vars := mux.Vars(r) vars := mux.Vars(r)
roomId := vars["roomId"] roomId := vars["roomId"]
userId := vars["userId"] userId := vars["userId"]
if roomId == "" || userId == "" { if roomId == "" || userId == "" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "GetPrepInfoToJoinHandler Missing Parameter"}); err != nil {
panic(err) panic(err)
} }
return return
@ -618,7 +615,7 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
homeserver := strings.Split(userId, ":") homeserver := strings.Split(userId, ":")
if len(homeserver) <= 1 { if len(homeserver) <= 1 {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Homeserver in UserId"}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "GetPrepInfoToJoinHandler Missing Homeserver in UserId"}); err != nil {
panic(err) panic(err)
} }
return return
@ -639,7 +636,7 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
memberEventContentBytes, err := json.Marshal(memberEventContent) memberEventContentBytes, err := json.Marshal(memberEventContent)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("GetPrepInfoToJoinHandler Could not parse JSON memberEventContent: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -662,7 +659,6 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
// TODO: TEST
func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) { func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := event.Event{} request := event.Event{}
@ -678,7 +674,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
err := decoder.Decode(&request) err := decoder.Decode(&request)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomServerHandler Could not parse JSON Request: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -688,7 +684,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
eventId := vars["eventId"] eventId := vars["eventId"]
if roomId == "" || eventId == "" { if roomId == "" || eventId == "" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Missing Parameter"}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "JoinRoomServerHandler Missing Parameter"}); err != nil {
panic(err) panic(err)
} }
return return
@ -708,32 +704,14 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
err = json.Unmarshal([]byte(request.Content), &memberEventContent) err = json.Unmarshal([]byte(request.Content), &memberEventContent)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Could not parse JSON: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomServerHandler Could not parse JSON MemberEventContent: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
} }
if memberEventContent.Membership != "join" { if memberEventContent.Membership != "join" {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "Wrong Membership"}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "JoinRoomServerHandler Wrong Membership"}); err != nil {
panic(err)
}
return
}
if err == nil {
err = event.CreateEvent(&request, "")
}
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Event-Creation: %s", err)}); err != nil {
panic(err)
}
return
}
CreateRoomMember(roomId, request.StateKey)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -741,7 +719,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
authChain, err := event.GetAuthChain(&request) authChain, err := event.GetAuthChain(&request)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Error Creating Auth Chain: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomServerHandler Error Creating Auth Chain: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return
@ -749,7 +727,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
stateEvents, err := event.ReadStateEventsFromRoom(roomId) stateEvents, err := event.ReadStateEventsFromRoom(roomId)
if err != nil { if err != nil {
w.WriteHeader(http.StatusBadRequest) w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("Database Error: %s", err)}); err != nil { if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomServerHandler Database Error ReadStateEventsFromRoom: %s", err)}); err != nil {
panic(err) panic(err)
} }
return return

View file

@ -3,6 +3,7 @@ package room
import ( import (
"fmt" "fmt"
"git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/entities/event" "git.nutfactory.org/hoernschen/Matrix/entities/event"
"git.nutfactory.org/hoernschen/Matrix/utils/database" "git.nutfactory.org/hoernschen/Matrix/utils/database"
) )
@ -34,17 +35,18 @@ func CreateRoom(room *Room) (err error) {
room.Federated, room.Federated,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
for _, userId := range room.Members { for _, userId := range room.Members {
err = CreateRoomMember(room.Id, userId) err = CreateRoomMember(room.Id, userId, config.Homeserver)
} }
return return
} }
func CreateRoomMember(roomId string, userId string) (err error) { func CreateRoomMember(roomId string, userId string, server string) (err error) {
return event.CreateRoomMember(roomId, userId) return event.CreateRoomMember(roomId, userId, server)
} }
func ReadRoom(id string) (foundRoom *Room, err error) { func ReadRoom(id string) (foundRoom *Room, err error) {
@ -121,6 +123,7 @@ func UpdateRoom(room *Room) (err error) {
room.Id, room.Id,
) )
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -137,8 +140,9 @@ func DeleteRoom(id string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -157,8 +161,9 @@ func DeleteRoomMember(roomId string, userId string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -175,8 +180,9 @@ func DeleteAllRoomMemberForUser(userId string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -193,8 +199,9 @@ func DeleteAllRoomMemberForRoom(roomId string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }

View file

@ -31,7 +31,7 @@ type RegisterRequest struct {
type RegisterResponse struct { type RegisterResponse struct {
UserId string `json:"user_id,omitempty"` UserId string `json:"user_id,omitempty"`
AccessToken string `json:"access_token,omitempty"` AccessToken string `json:"access_token,omitempty"`
HomeServer string `json:"home_server,omitempty"` sqllite string `json:"home_server,omitempty"`
DeviceId string `json:"device_id,omitempty"` DeviceId string `json:"device_id,omitempty"`
} }

View file

@ -26,6 +26,7 @@ func CreateUser(user *User) (err error) {
_, err = stmt.Exec(user.Id, user.Name, user.Password) _, err = stmt.Exec(user.Id, user.Name, user.Password)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
tx.Commit() tx.Commit()
@ -100,6 +101,7 @@ func UpdateUser(user *User) (err error) {
_, err = stmt.Exec(user.Name, user.Password, user.Id) _, err = stmt.Exec(user.Name, user.Password, user.Id)
if err != nil { if err != nil {
tx.Rollback()
return return
} }
@ -116,8 +118,9 @@ func DeleteUser(id string) (err error) {
return return
} }
_, err = database.DB.Exec(queryStmt) _, err = tx.Exec(queryStmt)
if err != nil { if err != nil {
tx.Rollback()
return return
} }

2
go.mod
View file

@ -5,6 +5,6 @@ go 1.14
require ( require (
github.com/cenkalti/backoff/v4 v4.1.0 github.com/cenkalti/backoff/v4 v4.1.0
github.com/gorilla/mux v1.8.0 github.com/gorilla/mux v1.8.0
github.com/lestrrat-go/backoff v1.0.0
github.com/mattn/go-sqlite3 v1.14.4 github.com/mattn/go-sqlite3 v1.14.4
github.com/urfave/cli v1.22.4
) )

7
go.sum
View file

@ -7,6 +7,7 @@ github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@ -14,16 +15,22 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lestrrat-go/backoff v1.0.0 h1:nR+UgAhdhwfw2i+xznuHRlj81oMYa7u3lXun0xcsXUU=
github.com/lestrrat-go/backoff v1.0.0/go.mod h1:c7OnDlnHsFXbH1vyIS8+txH+THcc+QFlSQTrJVe4EIM=
github.com/mattn/go-sqlite3 v1.14.3 h1:j7a/xn1U6TKA/PHHxqZuzh64CdtRc7rU9M+AvkOl5bA= github.com/mattn/go-sqlite3 v1.14.3 h1:j7a/xn1U6TKA/PHHxqZuzh64CdtRc7rU9M+AvkOl5bA=
github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI= github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI=
github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA= github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

24
main.go
View file

@ -5,6 +5,7 @@ import (
"log" "log"
"net/http" "net/http"
"os" "os"
"time"
"git.nutfactory.org/hoernschen/Matrix/config" "git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/entities/device" "git.nutfactory.org/hoernschen/Matrix/entities/device"
@ -14,6 +15,7 @@ import (
"git.nutfactory.org/hoernschen/Matrix/entities/user" "git.nutfactory.org/hoernschen/Matrix/entities/user"
"git.nutfactory.org/hoernschen/Matrix/utils/database" "git.nutfactory.org/hoernschen/Matrix/utils/database"
"git.nutfactory.org/hoernschen/Matrix/utils/router" "git.nutfactory.org/hoernschen/Matrix/utils/router"
"github.com/lestrrat-go/backoff"
) )
var keyPath = "./ssl.key" var keyPath = "./ssl.key"
@ -25,6 +27,7 @@ var routes = router.Routes{
router.Route{"ResolveServerName", "GET", "/.well-known/matrix/server", general.ResolveServerName}, router.Route{"ResolveServerName", "GET", "/.well-known/matrix/server", general.ResolveServerName},
router.Route{"GetServerImplementation", "GET", "/_matrix/federation/v1/version", general.GetServerImplementation}, router.Route{"GetServerImplementation", "GET", "/_matrix/federation/v1/version", general.GetServerImplementation},
router.Route{"Reset", "GET", "/reset", general.Reset}, router.Route{"Reset", "GET", "/reset", general.Reset},
router.Route{"SetParams", "GET", "/setparams", general.SetParams},
// Keys // Keys
router.Route{"GetSigningKey", "GET", "/_matrix/key/v2/server/{keyId}", device.GetServerSigningKeyHandler}, router.Route{"GetSigningKey", "GET", "/_matrix/key/v2/server/{keyId}", device.GetServerSigningKeyHandler},
@ -69,31 +72,22 @@ func main() {
config.VerifyKeys = make(map[string]map[string][]byte) config.VerifyKeys = make(map[string]map[string][]byte)
os.Remove("sqlite.db") os.Remove("sqlite.db")
config.BackoffPolicy = backoff.NewExponential(
backoff.WithInterval(500*time.Millisecond),
backoff.WithMaxRetries(16),
)
if err := database.InitDB("sqlite.db"); err != nil { if err := database.InitDB("sqlite.db"); err != nil {
log.Fatal(err) log.Fatal(err)
} }
defer database.DB.Close() defer database.DB.Close()
// TODO: Set Default Config Params here config.SetDefaultParams()
config.HttpString = "https"
router := router.NewRouter(routes) router := router.NewRouter(routes)
// TODO: Serve on Port 443 and 80 without Redirect
httpErr := http.ListenAndServeTLS(":443", certPath, keyPath, router) httpErr := http.ListenAndServeTLS(":443", certPath, keyPath, router)
if httpErr != nil { if httpErr != nil {
log.Fatal(httpErr) log.Fatal(httpErr)
} }
// TODO: TEST
httpErr = http.ListenAndServe(":80", router)
if httpErr != nil {
log.Fatal(httpErr)
}
/*
go http.ListenAndServe(":80", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "https://"+r.Host+r.URL.String(), http.StatusMovedPermanently)
}))
*/
} }

View file

@ -3,7 +3,6 @@ package database
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"log"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
) )
@ -11,7 +10,6 @@ import (
var DB *sql.DB var DB *sql.DB
func InitDB(filepath string) (err error) { func InitDB(filepath string) (err error) {
log.Printf("Init DB")
DB, err = sql.Open("sqlite3", filepath) DB, err = sql.Open("sqlite3", filepath)
if err != nil { if err != nil {
panic(err) panic(err)
@ -31,7 +29,6 @@ func InitDB(filepath string) (err error) {
} }
func initDeviceTable() (err error) { func initDeviceTable() (err error) {
log.Printf("Init Device Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS device ( statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS device (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
name TEXT, name TEXT,
@ -43,47 +40,10 @@ func initDeviceTable() (err error) {
} }
statement.Exec() statement.Exec()
/*
newDevice := &device.Device{Id: "test", Name: "TEST", Keys: nil}
err = CreateDevice(db, newDevice, "test")
if err != nil {
log.Printf("Error Create: %s", err)
return
}
newDevice.Name = "TEST2"
err = UpdateDevice(db, newDevice)
if err != nil {
log.Printf("Error Update: %s", err)
return
}
devices, err := ReadDevicesForUser(db, "test")
if err != nil {
log.Printf("Error Read User: %s", err)
return
}
log.Println(devices)
err = DeleteDevice(db, newDevice.Id)
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
de, err := ReadDevice(db, "test")
if err != nil {
log.Printf("Error Read: %s", err)
return
}
if de != nil {
log.Printf("Device ID: %s Name: %s", de.Id, de.Name)
} else {
log.Printf("No Device found")
}
*/
return return
} }
func initKeyTable() (err error) { func initKeyTable() (err error) {
log.Printf("Init Key Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS key ( statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS key (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
type TEXT, type TEXT,
@ -94,46 +54,11 @@ func initKeyTable() (err error) {
return return
} }
statement.Exec() statement.Exec()
/*
newKey := &device.Key{Id: "test", Type: "test", Key: "test"}
err = CreateKey(db, newKey, "test")
if err != nil {
log.Printf("Error Create: %s", err)
return
}
keys, err := ReadKeysForDevice(db, "test")
if err != nil {
log.Printf("Error Read Multiple: %s", err)
return
}
log.Println(keys)
newKey.Key = "TEST123"
err = UpdateKey(db, newKey)
if err != nil {
log.Printf("Error Update: %s", err)
return
}
err = DeleteKey(db, newKey.Id)
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
readKey, err := ReadKey(db, "test")
if err != nil {
log.Printf("Error Read: %s", err)
return
}
if readKey != nil {
log.Printf("Key ID: %s Type: %s, Key: %s", readKey.Id, readKey.Type, readKey.Key)
} else {
log.Printf("No Key found")
}
*/
return return
} }
func initEventTable() (err error) { func initEventTable() (err error) {
log.Printf("Init Event Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS event ( statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS event (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
roomId TEXT, roomId TEXT,
@ -172,60 +97,11 @@ func initEventTable() (err error) {
return return
} }
statement.Exec() statement.Exec()
/*
newEvent := &event.Event{
Id: "test",
RoomId: "test",
EventType: "test",
Content: "{TEST}",
ParentId: "test1",
Depth: 0,
}
err = CreateEvent(db, newEvent, "test")
if err != nil {
log.Printf("Error Create: %s", err)
return
}
eventsRoom, err := ReadEventsFromRoom(db, "test")
if err != nil {
log.Printf("Error Read User: %s", err)
return
}
log.Println(eventsRoom)
eventsTxn, err := ReadEventsFromTransaction(db, "test")
if err != nil {
log.Printf("Error Read User: %s", err)
return
}
log.Println(eventsTxn)
newEvent.Content = "{TEST123}"
err = UpdateEvent(db, newEvent)
if err != nil {
log.Printf("Error Update: %s", err)
return
}
err = DeleteEvent(db, newEvent.Id)
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
readEvent, err := ReadEvent(db, "test")
if err != nil {
log.Printf("Error Read: %s", err)
return
}
if readEvent != nil {
log.Printf("Event ID: %s RoomId: %s EventType: %s Content: %s ParentId: %s Depth: %s",
readEvent.Id, readEvent.RoomId, readEvent.EventType, readEvent.Content, readEvent.ParentId, readEvent.Depth)
} else {
log.Printf("No Event found")
}
*/
return return
} }
func initRoomTable() (err error) { func initRoomTable() (err error) {
log.Printf("Init Room Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS room ( statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS room (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
version TEXT, version TEXT,
@ -249,61 +125,11 @@ func initRoomTable() (err error) {
return return
} }
statement.Exec() statement.Exec()
/*
newRoom := &room.Room{Id: "test", Version: "test"}
err = CreateRoom(db, newRoom, "test")
if err != nil {
log.Printf("Error Create: %s", err)
return
}
err = CreateRoomMember(db, newRoom.Id, "test2")
if err != nil {
log.Printf("Error Create: %s", err)
return
}
roomMembers, err := ReadRoomMembers(db, newRoom.Id)
if err != nil {
log.Printf("Error Read Members: %s", err)
return
}
log.Println(roomMembers)
newRoom.Version = "test2"
err = UpdateRoom(db, newRoom)
if err != nil {
log.Printf("Error Update: %s", err)
return
}
err = DeleteRoomMember(db, newRoom.Id, "test")
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
err = DeleteAllRoomMemberForUser(db, "test2")
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
err = DeleteRoom(db, newRoom.Id)
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
readRoom, err := ReadRoom(db, newRoom.Id)
if err != nil {
log.Printf("Error Read: %s", err)
return
}
if readRoom != nil {
log.Printf("Room ID: %s Version: %s Members: %s", readRoom.Id, readRoom.Version, readRoom.Members)
} else {
log.Printf("No Room found")
}
*/
return return
} }
func initTransactionTable() (err error) { func initTransactionTable() (err error) {
log.Printf("Init Transaction Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS txn ( statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS txn (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
origin TEXT, origin TEXT,
@ -314,40 +140,10 @@ func initTransactionTable() (err error) {
} }
statement.Exec() statement.Exec()
/*
newTransaction := &transaction.Transaction{Id: "test", Origin: "test.de", Timestamp: 1234}
err = CreateTransaction(db, newTransaction)
if err != nil {
log.Printf("Error Create: %s", err)
return
}
newTransaction.Origin = "test2.de"
err = UpdateTransaction(db, newTransaction)
if err != nil {
log.Printf("Error Update: %s", err)
return
}
err = DeleteTransaction(db, newTransaction.Id)
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
readTransaction, err := ReadTransaction(db, newTransaction.Id)
if err != nil {
log.Printf("Error Read: %s", err)
return
}
if readTransaction != nil {
log.Printf("Transaction ID: %s Origin: %s Timestamp: %s PDUS: %s", readTransaction.Id, readTransaction.Origin, readTransaction.Timestamp, readTransaction.PDUS)
} else {
log.Printf("No Transaction found")
}
*/
return return
} }
func initUserTable() (err error) { func initUserTable() (err error) {
log.Printf("Init User Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS user ( statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS user (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
name TEXT, name TEXT,
@ -358,36 +154,6 @@ func initUserTable() (err error) {
} }
statement.Exec() statement.Exec()
/*
newUser := &user.User{Id: "test", Name: "test", Password: "test"}
err = CreateUser(db, newUser)
if err != nil {
log.Printf("Error Create: %s", err)
return
}
newUser.Name = "TEST2"
err = UpdateUser(db, newUser)
if err != nil {
log.Printf("Error Update: %s", err)
return
}
err = DeleteUser(db, newUser.Id)
if err != nil {
log.Printf("Error Delete: %s", err)
return
}
readUser, err := ReadUser(db, newUser.Id)
if err != nil {
log.Printf("Error Read: %s", err)
return
}
if readUser != nil {
log.Printf("User ID: %s Name: %s Password: %s Devices: %s", readUser.Id, readUser.Name, readUser.Password, readUser.Devices)
} else {
log.Printf("No User found")
}
*/
return return
} }

View file

@ -49,17 +49,26 @@ func GenerateKeyPair() (publicKey ed25519.PublicKey, privateKey ed25519.PrivateK
return return
} }
func Sign(message []byte) []byte { func Sign(message []byte) string {
return ed25519.Sign(config.PrivateKey, message) signatureBytes := ed25519.Sign(config.PrivateKey, message)
return base64.RawStdEncoding.EncodeToString(signatureBytes)
} }
func SignContent(content []byte) (signatures map[string]map[string]string) { func SignContent(content []byte) (signatures map[string]map[string]string) {
signatures = make(map[string]map[string]string) signatures = make(map[string]map[string]string)
signatures[config.Homeserver] = make(map[string]string) signatures[config.Homeserver] = make(map[string]string)
signatures[config.Homeserver][config.KeyId] = string(Sign(content)) if !config.Signing {
return
}
signatures[config.Homeserver][config.KeyId] = Sign(content)
return return
} }
func VerifySignature(publicKey []byte, message []byte, signature []byte) bool { func VerifySignature(publicKey []byte, message []byte, signature string) bool {
return ed25519.Verify(publicKey, message, signature) signatureBytes, err := base64.RawStdEncoding.DecodeString(signature)
if err != nil {
return false
}
ed25519.Verify(config.PublicKey, message, signatureBytes)
return true
} }

View file

@ -1,9 +1,9 @@
package utils package utils
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log"
"net/http" "net/http"
"strings" "strings"
@ -32,7 +32,10 @@ func CheckRequest(r *http.Request) (response *ErrorResponse) {
return return
} }
func CheckAuthHeader(r *http.Request) (response *ErrorResponse) { func CheckAuthHeader(r *http.Request, content string) (response *ErrorResponse) {
if !config.AuthentificationCheck {
return
}
authHeader := r.Header.Get("Authorization") authHeader := r.Header.Get("Authorization")
if authHeader == "" || !strings.Contains(authHeader, "X-Matrix") { if authHeader == "" || !strings.Contains(authHeader, "X-Matrix") {
response = &ErrorResponse{ErrorMessage: "Missing Authorization Header"} response = &ErrorResponse{ErrorMessage: "Missing Authorization Header"}
@ -40,15 +43,12 @@ func CheckAuthHeader(r *http.Request) (response *ErrorResponse) {
} }
keys := strings.Split(authHeader, ",") keys := strings.Split(authHeader, ",")
origin := strings.Split(keys[0], "=")[1] origin := strings.Split(keys[0], "=")[1]
if !strings.Contains(keys[2], "ed25519") { if !strings.Contains(keys[1], "ed25519") {
response = &ErrorResponse{ErrorMessage: "Missing ed25519 Signature Key"} response = &ErrorResponse{ErrorMessage: "Missing ed25519 Signature Key"}
return return
} }
key := strings.Split(strings.Replace(strings.Split(keys[2], "=")[1], "\"", "", 2), ":")[1] key := strings.Split(strings.Replace(strings.Split(keys[1], "=")[1], "\"", "", 2), ":")[1]
signature := strings.Replace(strings.Split(keys[2], "=")[1], "\"", "", 2) signature := strings.Replace(strings.Split(keys[2], "=")[1], "\"", "", 2)
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
content := buf.String()
requestSummary := RequestSummary{ requestSummary := RequestSummary{
Method: r.Method, Method: r.Method,
Uri: r.RequestURI, Uri: r.RequestURI,
@ -61,7 +61,7 @@ func CheckAuthHeader(r *http.Request) (response *ErrorResponse) {
response = &ErrorResponse{ErrorMessage: "Error Creating Auth JSON String"} response = &ErrorResponse{ErrorMessage: "Error Creating Auth JSON String"}
return return
} }
correct := VerifySignature([]byte(key), requestSummaryString, []byte(signature)) correct := VerifySignature([]byte(key), requestSummaryString, signature)
if !correct { if !correct {
response = &ErrorResponse{ErrorMessage: "Signature in Auth Header is incorrect"} response = &ErrorResponse{ErrorMessage: "Signature in Auth Header is incorrect"}
return return
@ -81,7 +81,7 @@ func CreateAuthHeader(method string, uri string, destination string, content str
if err != nil { if err != nil {
return return
} }
authHeader = fmt.Sprintf("X-Matrix origin=%s,key=\"%s\",sig=\"%s\"", config.Homeserver, config.KeyId, Sign(SigningContent)) authHeader = fmt.Sprintf("X-Matrix origin=%s,key=%s,sig=%s", config.Homeserver, config.KeyId, Sign(SigningContent))
return return
} }
@ -98,6 +98,19 @@ func GetAccessToken(r *http.Request) (token string, response *ErrorResponse) {
return return
} }
func HandleHTTPError(res *http.Response) (response *ErrorResponse) {
log.Printf("Statuscode %s", res.Status)
response = &ErrorResponse{}
decoder := json.NewDecoder(res.Body)
err := decoder.Decode(response)
if err != nil {
log.Printf("Error not parseable")
return
}
log.Printf("%s (%s)", response.ErrorMessage, response.ErrorCode)
return
}
func IsJSONString(s string) bool { func IsJSONString(s string) bool {
var js string var js string
return json.Unmarshal([]byte(s), &js) == nil return json.Unmarshal([]byte(s), &js) == nil

626
workloadGenerator.go Normal file
View file

@ -0,0 +1,626 @@
package main
import (
"bytes"
"crypto/tls"
"encoding/base64"
"encoding/csv"
"encoding/json"
"fmt"
"log"
"math/rand"
"net/http"
"os"
"strconv"
"strings"
"time"
"git.nutfactory.org/hoernschen/Matrix/entities/event"
"git.nutfactory.org/hoernschen/Matrix/entities/general"
"git.nutfactory.org/hoernschen/Matrix/entities/room"
"git.nutfactory.org/hoernschen/Matrix/entities/user"
"git.nutfactory.org/hoernschen/Matrix/utils"
)
var BaseLineTest = true
var systemParamsIndex = 0
type SystemParams struct {
Id string
BytesToSend int
MessagesPerSecond float32
Distribution map[string][]string
Packetloss int
MinutesNotAvailable int
Consensus bool
AuthentificationCheck bool
Signing bool
Encryption bool
}
var httpString string
var users = []map[string][]string{
map[string][]string{
"143.93.38.208": []string{
"user1",
"user2",
"user3",
"user4",
"user5",
"user6",
},
},
map[string][]string{
"143.93.38.207": []string{
"user1",
"user2",
"user3",
"user4",
},
"143.93.38.208": []string{
"user1",
},
"143.93.38.209": []string{
"user1",
},
},
map[string][]string{
"143.93.38.207": []string{
"user1",
"user2",
"user3",
"user4",
},
"143.93.38.208": []string{
"user1",
"user2",
"user3",
"user4",
},
"143.93.38.209": []string{
"user1",
"user2",
"user3",
"user4",
},
},
}
var servers = []string{
"143.93.38.207",
"143.93.38.208",
"143.93.38.209",
}
var systemParams = []SystemParams{
SystemParams{
Id: "111111111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
/*
SystemParams{
Id: "011111111",
BytesToSend: 8,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "211111111",
BytesToSend: 512,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "101111111",
BytesToSend: 280,
MessagesPerSecond: 0.1,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "121111111",
BytesToSend: 280,
MessagesPerSecond: 10.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "110111111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[0],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "112111111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[2],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "111011111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 0,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "111211111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 20,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "111121111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 1,
Consensus: true,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "111110111",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: false,
AuthentificationCheck: true,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "111111011",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: false,
Signing: true,
Encryption: true,
},
SystemParams{
Id: "111111101",
BytesToSend: 280,
MessagesPerSecond: 1.0,
Distribution: users[1],
Packetloss: 1,
MinutesNotAvailable: 0,
Consensus: true,
AuthentificationCheck: true,
Signing: false,
Encryption: true,
},
*/
}
var userIds []string
var accessTokens map[string]string
var roomId string
func getCSVWriter(filename string) (writer *csv.Writer) {
file, err := os.Create(fmt.Sprintf("%s %s.csv", strconv.FormatInt(time.Now().Unix(), 10), filename))
if err != nil {
log.Fatalf("Error Creating CSV: %s", err)
}
defer file.Close()
writer = csv.NewWriter(file)
return
}
func main() {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
httpString = "https"
iteration := 0
if BaseLineTest {
file, err := os.Create(fmt.Sprintf("%s Baseline Measurement.csv", strconv.FormatInt(time.Now().Unix(), 10)))
if err != nil {
log.Fatalf("Error Creating CSV: %s", err)
}
defer file.Close()
writer := csv.NewWriter(file)
defer writer.Flush()
err = writer.Write([]string{"Iteration", "Start", "End"})
if err != nil {
log.Fatalf("Error in Writing CSV: %s", err)
}
for iteration < 10 {
log.Printf("Iteration: %s", strconv.Itoa(iteration))
start := time.Now().Unix()
time.Sleep(2 * time.Minute)
end := time.Now().Unix()
iteration++
err = writer.Write([]string{strconv.Itoa(iteration), strconv.FormatInt(start, 10), strconv.FormatInt(end, 10)})
if err != nil {
log.Fatalf("Error in Writing CSV: %s", err)
}
}
} else {
for _, systemParam := range systemParams {
file, err := os.Create(fmt.Sprintf("%s %s Measurement Matrix.csv", strconv.FormatInt(time.Now().Unix(), 10), systemParam.Id))
if err != nil {
log.Fatalf("Error Creating CSV: %s", err)
}
writer := csv.NewWriter(file)
err = writer.Write([]string{"Iteration", "Start", "End", "Actions Send"})
if err != nil {
log.Fatalf("Error in Writing CSV: %s", err)
}
millisecondsToWait := 1000 / systemParam.MessagesPerSecond
iteration = 0
for iteration < 30 {
err := setUp(systemParam)
if err != nil {
log.Fatalf("Error in SetUp: %s", err)
}
b := make([]byte, systemParam.BytesToSend)
_, err = rand.Read(b)
message := base64.RawStdEncoding.EncodeToString(b)
start := time.Now()
end := start.Add(2 * time.Minute).Unix()
log.Printf("Id: %s - Iteration: %s - Start: %s - End: %s", systemParam.Id, strconv.Itoa(iteration), strconv.FormatInt(start.Unix(), 10), strconv.FormatInt(end, 10))
actionsSend := 0
for time.Now().Unix() < end {
time.Sleep(time.Duration(millisecondsToWait) * time.Millisecond)
err = sendMessage(message)
if err != nil {
log.Fatalf("Error sending Message %s", err)
}
actionsSend++
}
iteration++
err = writer.Write([]string{strconv.Itoa(iteration), strconv.FormatInt(start.Unix(), 10), strconv.FormatInt(end, 10), strconv.Itoa(actionsSend)})
if err != nil {
log.Fatalf("Error in Writing CSV: %s", err)
}
time.Sleep(1 * time.Second)
err = reset()
if err != nil {
log.Fatalf("Error in Reset: %s", err)
}
time.Sleep(1 * time.Second)
}
writer.Flush()
file.Close()
}
}
}
func sendMessage(message string) (err error) {
userIndex := rand.Intn(3)
userId := userIds[userIndex]
accessToken := accessTokens[userId]
err, txnId := utils.CreateUUID()
if err != nil {
return
}
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/rooms/%s/send/m.room.message/%s", httpString, strings.Split(userId, ":")[1], roomId, txnId)
request := event.SendMessageRequest{
MessageType: "m.text",
Body: message,
}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{}
var req *http.Request
req, err = http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", accessToken)}
res, err := client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
handleError(res)
}
return
}
func setParams(systemParamsToUse SystemParams) (err error) {
serverNotAvailableIndex := 1
for i, server := range servers {
minutesNotAvailable := 0
if serverNotAvailableIndex == i {
minutesNotAvailable = systemParamsToUse.MinutesNotAvailable
}
requestUrl := fmt.Sprintf("%s://%s/setparams", httpString, server)
request := general.SetParamBody{
Packetloss: systemParamsToUse.Packetloss,
UnavailableTill: time.Now().Add(time.Duration(minutesNotAvailable) * time.Minute).Unix(),
Consensus: systemParamsToUse.Consensus,
AuthentificationCheck: systemParamsToUse.AuthentificationCheck,
Signing: systemParamsToUse.Signing,
Encryption: systemParamsToUse.Encryption,
}
var reqBody []byte
reqBody, err = json.Marshal(request)
if err != nil {
return
}
client := &http.Client{Timeout: 10 * time.Second}
var req *http.Request
req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
var res *http.Response
res, err = client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
handleError(res)
}
}
return
}
func setUp(systemParamsToUse SystemParams) (err error) {
accessTokens = make(map[string]string)
err = createUsers(systemParamsToUse.Distribution)
if err != nil {
log.Printf("Error in User-Creation: %s", err)
return
}
// Create Room
err = createRoom(userIds[0])
if err != nil {
log.Printf("Error in Room-Creation: %s", err)
return
}
// Join to Room
err = joinRoom(userIds[1:])
if err != nil {
log.Printf("Error joining Room: %s", err)
return
}
err = setParams(systemParamsToUse)
return
}
func reset() (err error) {
roomId = ""
userIds = []string{}
accessTokens = make(map[string]string)
for _, server := range servers {
requestUrl := fmt.Sprintf("%s://%s/reset", httpString, server)
client := &http.Client{Timeout: 10 * time.Second}
var req *http.Request
req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(nil))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
var res *http.Response
res, err = client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
handleError(res)
}
}
return
}
func createRoom(userId string) (err error) {
accessToken := accessTokens[userId]
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/createRoom", httpString, strings.Split(userId, ":")[1])
request := room.CreateRoomRequest{
Visibility: "public",
Name: "Testraum",
Topic: "Raum für die Energieeffizienz-Tests",
RoomVersion: "1",
CreationContent: room.CreationContent{
Federated: true,
},
Preset: "public_chat",
IsDirect: true,
}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{Timeout: 10 * time.Second}
req, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", accessToken)}
res, err := client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
handleError(res)
} else {
response := room.CreateRoomResponse{}
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
roomId = response.RoomId
log.Printf("Room created: %s", roomId)
}
return
}
func joinRoom(userIdsToJoin []string) (err error) {
for _, userId := range userIdsToJoin {
err = joinRoomUser(userId)
if err != nil {
return
}
//time.Sleep(time.Duration(1) * time.Second)
}
return
}
func joinRoomUser(userId string) (err error) {
log.Printf("Join %s to %s", userId, roomId)
accessToken := accessTokens[userId]
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/rooms/%s/join", httpString, strings.Split(userId, ":")[1], roomId)
request := room.JoinRoomUserRequest{}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{Timeout: 10 * time.Second}
req, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", accessToken)}
res, err := client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
handleError(res)
} else {
response := room.JoinRoomUserResponse{}
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
roomId = response.RoomId
log.Printf("%s joined Room", userId)
}
return
}
func createUsers(serverUserMap map[string][]string) (err error) {
for server, usersToCreate := range serverUserMap {
for _, userToCreate := range usersToCreate {
var userId string
var accessToken string
userId, accessToken, err = createUser(userToCreate, server)
if err != nil {
return
}
if userId != "" && accessToken != "" {
log.Printf("%s created - AccessToken: %s", userId, accessToken)
accessTokens[userId] = accessToken
userIds = append(userIds, userId)
}
}
}
return
}
func createUser(userToCreate string, homeserver string) (userId string, accessToken string, err error) {
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/register", httpString, homeserver)
request := user.RegisterRequest{
Auth: user.AuthentificationData{
LoginType: "m.login.password",
},
Username: userToCreate,
Password: "password",
DeviceName: fmt.Sprintf("%s's device", userToCreate),
}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{Timeout: 10 * time.Second}
req, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
res, err := client.Do(req)
if err != nil {
return
}
if res.StatusCode != http.StatusOK {
handleError(res)
} else {
response := user.RegisterResponse{}
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
userId = response.UserId
accessToken = response.AccessToken
}
return
}
func handleError(res *http.Response) {
utils.HandleHTTPError(res)
}

View file

@ -1,209 +0,0 @@
package workloadgenerator
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
"git.nutfactory.org/hoernschen/Matrix/entities/room"
"git.nutfactory.org/hoernschen/Matrix/entities/user"
"git.nutfactory.org/hoernschen/Matrix/utils"
)
var httpString = "http"
var servers = []string{
"localhost",
}
var userIds []string
var accessTokens map[string]string
var roomId string
var users = []string{
"user1",
"user2",
"user3",
"user4",
"user5",
"user6",
}
func main() {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
accessTokens = make(map[string]string)
err := createUsers()
if err != nil {
log.Printf("Error in User-Creation: %s", err)
return
}
// Create Room
err = createRoom(userIds[0])
if err != nil {
log.Printf("Error in Room-Creation: %s", err)
return
}
// Join to Room
err = joinRoom(userIds[1:])
if err != nil {
log.Printf("Error joining Room: %s", err)
return
}
// Send Messages with Timer
}
func reset() (err error) {
// TODO: Implement
return
}
func createRoom(userId string) (err error) {
accessToken := accessTokens[userId]
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/createRoom", httpString, strings.Split(userId, ":")[1])
request := room.CreateRoomRequest{
Visibility: "public",
Name: "Testraum",
Topic: "Raum für die Energieeffizienz-Tests",
RoomVersion: "1",
CreationContent: room.CreationContent{
Federated: true,
},
Preset: "public_chat",
IsDirect: true,
}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", accessToken)}
res, err := client.Do(req)
if res.StatusCode != http.StatusOK {
handleError(res)
} else {
response := room.CreateRoomResponse{}
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
roomId = response.RoomId
log.Printf("Room created: %s", roomId)
}
return
}
func joinRoom(userIdsToJoin []string) (err error) {
for _, userId := range userIdsToJoin {
err = joinRoomUser(userId)
if err != nil {
return
}
}
return
}
func joinRoomUser(userId string) (err error) {
accessToken := accessTokens[userId]
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/rooms/%s/join", httpString, strings.Split(userId, ":")[1], roomId)
request := room.JoinRoomUserRequest{}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
req.Header["Authorization"] = []string{fmt.Sprintf("Bearer %s", accessToken)}
res, err := client.Do(req)
if res.StatusCode != http.StatusOK {
handleError(res)
} else {
response := room.JoinRoomUserResponse{}
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
roomId = response.RoomId
log.Printf("%s joined Room", userId)
}
return
}
func createUsers() (err error) {
for _, userToCreate := range users {
var userId string
var accessToken string
userId, accessToken, err = createUser(userToCreate, "localhost")
if err != nil {
return
}
if userId != "" && accessToken != "" {
log.Printf("%s: %s", userId, accessToken)
accessTokens[userId] = accessToken
userIds = append(userIds, userId)
}
}
return
}
func createUser(userToCreate string, homeserver string) (userId string, accessToken string, err error) {
requestUrl := fmt.Sprintf("%s://%s/_matrix/client/r0/register", httpString, homeserver)
request := user.RegisterRequest{
Auth: user.AuthentificationData{
LoginType: "m.login.password",
},
Username: userToCreate,
Password: "password",
DeviceName: fmt.Sprintf("%s's device", userToCreate),
}
reqBody, err := json.Marshal(request)
if err != nil {
return
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPost, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
res, err := client.Do(req)
if res.StatusCode != http.StatusOK {
handleError(res)
} else {
response := user.RegisterResponse{}
decoder := json.NewDecoder(res.Body)
err = decoder.Decode(&response)
if err != nil {
return
}
userId = response.UserId
accessToken = response.AccessToken
}
return
}
func handleError(res *http.Response) {
response := utils.ErrorResponse{}
decoder := json.NewDecoder(res.Body)
err := decoder.Decode(&response)
if err != nil {
log.Printf("Error not parseable")
return
}
log.Printf("%s (%s)", response.ErrorMessage, response.ErrorCode)
}