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",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/main.go",
"program": "${workspaceFolder}/workloadGenerator.go",
"env": {},
"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
import (
"time"
"github.com/lestrrat-go/backoff"
)
var ServerName string = "Hoernschen's Matrix Server"
var Version string = "0.1"
@ -11,11 +17,22 @@ var PublicKey []byte
var KeyId string
var VerifyKeys map[string]map[string][]byte
// Parameters for Mesurements
// TODO: Implement correctly
var Packetloss float32
var UnavailableTill int
var Packetloss int
var UnavailableTill int64
var Consensus bool
var AuthentificationCheck bool
var Signing bool
var Encryption bool
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 (
"fmt"
"log"
"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)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
@ -60,7 +60,7 @@ func ReadDeviceFromAccessToken(accessToken string) (foundDevice *Device, err err
queryStmt := fmt.Sprintf(`SELECT id, name, accessToken
FROM device
WHERE accessToken = '%s'`, accessToken)
log.Printf(queryStmt)
rows, err := database.DB.Query(queryStmt)
if err != nil {
return
@ -126,6 +126,7 @@ func UpdateDevice(device *Device) (err error) {
_, err = stmt.Exec(device.Name, device.AccessToken, device.Id)
if err != nil {
tx.Rollback()
return
}
@ -142,8 +143,9 @@ func DeleteDevice(id string) (err error) {
return
}
_, err = database.DB.Exec(queryStmt)
_, err = tx.Exec(queryStmt)
if err != nil {
tx.Rollback()
return
}

View file

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

View file

@ -1,9 +1,12 @@
package device
import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"time"
"git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/utils"
@ -28,11 +31,11 @@ func GetServerSigningKeyHandler(w http.ResponseWriter, r *http.Request) {
}
return
}
response := serverKeys{
response := ServerKeys{
ServerName: config.Homeserver,
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)
if err != nil {
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 {
key = val
} else {
httpString := "https"
requestUrl := fmt.Sprintf("%s://%s/_matrix/key/v2/server", httpString, server)
var res *http.Response
res, err = http.Get(requestUrl)
requestUrl := fmt.Sprintf("%s://%s/_matrix/key/v2/server", config.HttpString, server)
client := &http.Client{Timeout: 2 * time.Second}
var req *http.Request
req, err = http.NewRequest(http.MethodGet, requestUrl, bytes.NewBuffer(nil))
if err != nil {
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)
err = decoder.Decode(&serverKeyRes)
config.VerifyKeys[server] = make(map[string][]byte)
for keyId, verifyKey := range serverKeyRes.VerifyKeys {
config.VerifyKeys[server][keyId] = []byte(verifyKey.Key)
verifyKeyBytes, err := base64.RawStdEncoding.DecodeString(verifyKey.Key)
if err == nil {
config.VerifyKeys[server][keyId] = verifyKeyBytes
if id == keyId {
key = []byte(verifyKey.Key)
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)
if err != nil {
tx.Rollback()
return
}
tx.Commit()
@ -99,6 +100,7 @@ func UpdateKey(key *Key) (err error) {
_, err = stmt.Exec(key.Type, key.Key, key.Id)
if err != nil {
tx.Rollback()
return
}
@ -115,8 +117,9 @@ func DeleteKey(id string) (err error) {
return
}
_, err = database.DB.Exec(queryStmt)
_, err = tx.Exec(queryStmt)
if err != nil {
tx.Rollback()
return
}

View file

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

View file

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

View file

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

View file

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

View file

@ -6,6 +6,7 @@ import (
"log"
"net/http"
"os"
"time"
"git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/entities/device"
@ -26,9 +27,10 @@ type serverImplementation struct {
Version string `json:"version,omitempty"`
}
type ResetBody struct {
Packetloss float32 `json:"packetloss,omitempty"`
UnavailableTill int `json:"unavailableTill,omitempty"`
type SetParamBody struct {
Packetloss int `json:"packetloss,omitempty"`
UnavailableTill int64 `json:"unavailableTill,omitempty"`
Consensus bool `json:"consensus,omitempty"`
AuthentificationCheck bool `json:"authentificationCheck,omitempty"`
Signing bool `json:"signing,omitempty"`
Encryption bool `json:"encryption,omitempty"`
@ -52,10 +54,9 @@ func GetServerImplementation(w http.ResponseWriter, r *http.Request) {
}
}
// TODO: Add a function to set the Config-Params
func Reset(w http.ResponseWriter, r *http.Request) {
func SetParams(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := ResetBody{}
request := SetParamBody{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
@ -74,22 +75,45 @@ func Reset(w http.ResponseWriter, r *http.Request) {
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 {
log.Fatal(err)
}
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)
}
config.Packetloss = request.Packetloss
config.UnavailableTill = request.UnavailableTill
config.AuthentificationCheck = request.AuthentificationCheck
config.Signing = request.Signing
config.Encryption = request.Signing
config.SetDefaultParams()
w.WriteHeader(http.StatusOK)
}

View file

@ -34,8 +34,6 @@ type CreateRoomResponse struct {
RoomId string `json:"room_id,omitempty"`
}
type getRoomMemberRequest struct{}
type getRoomMemberResponse struct {
Chunk []*event.Event `json:"chunk,omitempty"`
}
@ -48,12 +46,6 @@ type JoinRoomUserResponse struct {
RoomId string `json:"room_id,omitempty"`
}
type leaveRoomUserRequest struct{}
type leaveRoomUserResponse struct{}
type makeJoinRequest struct{}
type makeJoinResponse struct {
RoomVersion string `json:"room_version,omitempty"`
Event event.Event `json:"event,omitempty"`
@ -74,14 +66,6 @@ type joinRoomServerResponse struct {
State []*event.Event `json:"state,omitempty"`
}
type makeLeaveRequest struct{}
type makeLeaveResponse struct{}
type leaveRoomServerRequest struct{}
type leaveRoomServerResponse struct{}
type invite3pid struct {
IdServer string `json:"id_server,omitempty"`
IdAccessToken string `json:"id_access_token,omitempty"`
@ -107,8 +91,6 @@ type invite struct {
type thirdPartySigned struct {
Sender string `json:"sender,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"`
}
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) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := getRoomMemberRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
@ -349,16 +348,6 @@ func GetRoomMemberHandler(w http.ResponseWriter, r *http.Request) {
}
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)
roomId := vars["roomId"]
if roomId == "" {
@ -407,7 +396,7 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Could not parse JSON Request: %s", err)}); err != nil {
panic(err)
}
return
@ -416,7 +405,7 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
roomId := vars["roomId"]
if roomId == "" {
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)
}
return
@ -424,49 +413,46 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
foundRoom, err := ReadRoom(roomId)
if err != nil {
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)
}
return
}
var joinEvent *event.Event
if foundRoom == nil {
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: true,
Membership: "join",
}
memberEventContentBytes, _ := json.Marshal(memberEventContent)
err, memberEvent := event.New(
roomId,
foundUser.Id,
config.Homeserver,
time.Now().Unix(),
"m.room.member",
foundUser.Id,
string(memberEventContentBytes),
"",
)
if err == nil {
err = event.CreateEvent(memberEvent, "")
server := strings.Split(roomId, ":")[1]
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/make_join/%s/%s", config.HttpString, server, roomId, foundUser.Id)
client := &http.Client{Timeout: 2 * 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"}
res, err := client.Do(req)
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Error Getting Response Make JSON: %s", err)}); err != nil {
panic(err)
}
return
}
httpString := "https"
server := strings.Split(roomId, ":")[1]
requestUrl := fmt.Sprintf("%s://%s/_matrix/federation/v1/make_join/%s/%s", httpString, server, roomId, foundUser.Id)
res, err := http.Get(requestUrl)
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
}
}
makeJoinRes := makeJoinResponse{}
decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&makeJoinRes)
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Could not parse JSON makeJoinResponse: %s", err)}); err != nil {
panic(err)
}
return
@ -474,7 +460,7 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
err = CreateRoom(&Room{Id: roomId, Version: makeJoinRes.RoomVersion})
if err != nil {
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)
}
return
@ -489,36 +475,54 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
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)
if err != nil {
return
}
client := &http.Client{}
req, err := http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
client = &http.Client{Timeout: 2 * time.Second}
req, err = http.NewRequest(http.MethodPut, requestUrl, bytes.NewBuffer(reqBody))
if err != nil {
return
}
req.Header["Content-Type"] = []string{"application/json"}
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{}
decoder = json.NewDecoder(res.Body)
err = decoder.Decode(&joinRes)
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomUserHandler Could not parse JSON joinRoomServerResponse: %s", err)}); err != nil {
panic(err)
}
return
}
err = event.HandleEvents(joinRes.State)
err = event.HandleEvents(joinRes.State, "")
if err != nil {
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)
}
return
}
} else {
}
memberEventContent := event.MemberEventContent{
DisplayName: foundUser.Name,
IsDirect: true,
@ -535,16 +539,16 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
string(memberEventContentBytes),
"",
)
}
err, txnId := utils.CreateUUID()
err = event.CreateEvent(joinEvent, txnId)
if err != nil {
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)
}
return
}
event.HandleEvent(joinEvent, "")
transaction := &event.Transaction{
Id: txnId,
Origin: config.Homeserver,
@ -554,30 +558,33 @@ func JoinRoomUserHandler(w http.ResponseWriter, r *http.Request) {
servers, err := event.ReadServers(roomId)
if err != nil {
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)
}
return
}
for _, server := range servers {
//if server != config.Homeserver {
if server != config.Homeserver {
log.Printf("Send Transaction to %s", server)
operation := func() error {
return event.SendTransaction(transaction, server)
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)
}
go backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
//}
backoff.RetryNotify(operation, backoff.NewExponentialBackOff(), notify)
}
err = CreateRoomMember(roomId, foundUser.Id)
}
/*
err = CreateRoomMember(roomId, foundUser.Id, config.Homeserver)
if err != nil {
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 CreateRoomMember: %s", err)}); err != nil {
panic(err)
}
return
}
*/
response := JoinRoomUserResponse{RoomId: roomId}
w.WriteHeader(http.StatusOK)
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) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := makeJoinRequest{}
errResponse := utils.CheckRequest(r)
if errResponse != nil {
w.WriteHeader(http.StatusBadRequest)
@ -596,21 +602,12 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
}
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)
roomId := vars["roomId"]
userId := vars["userId"]
if roomId == "" || userId == "" {
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)
}
return
@ -618,7 +615,7 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
homeserver := strings.Split(userId, ":")
if len(homeserver) <= 1 {
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)
}
return
@ -639,7 +636,7 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
memberEventContentBytes, err := json.Marshal(memberEventContent)
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("GetPrepInfoToJoinHandler Could not parse JSON memberEventContent: %s", err)}); err != nil {
panic(err)
}
return
@ -662,7 +659,6 @@ func GetPrepInfoToJoinHandler(w http.ResponseWriter, r *http.Request) {
}
}
// TODO: TEST
func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
request := event.Event{}
@ -678,7 +674,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomServerHandler Could not parse JSON Request: %s", err)}); err != nil {
panic(err)
}
return
@ -688,7 +684,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
eventId := vars["eventId"]
if roomId == "" || eventId == "" {
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)
}
return
@ -708,32 +704,14 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
err = json.Unmarshal([]byte(request.Content), &memberEventContent)
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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: fmt.Sprintf("JoinRoomServerHandler Could not parse JSON MemberEventContent: %s", err)}); err != nil {
panic(err)
}
return
}
if memberEventContent.Membership != "join" {
w.WriteHeader(http.StatusBadRequest)
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "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 {
if err := json.NewEncoder(w).Encode(utils.ErrorResponse{ErrorMessage: "JoinRoomServerHandler Wrong Membership"}); err != nil {
panic(err)
}
return
@ -741,7 +719,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
authChain, err := event.GetAuthChain(&request)
if err != nil {
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)
}
return
@ -749,7 +727,7 @@ func JoinRoomServerHandler(w http.ResponseWriter, r *http.Request) {
stateEvents, err := event.ReadStateEventsFromRoom(roomId)
if err != nil {
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)
}
return

View file

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

View file

@ -31,7 +31,7 @@ type RegisterRequest struct {
type RegisterResponse struct {
UserId string `json:"user_id,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"`
}

View file

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

2
go.mod
View file

@ -5,6 +5,6 @@ go 1.14
require (
github.com/cenkalti/backoff/v4 v4.1.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/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/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/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/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
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/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/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/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI=
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/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/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/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/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/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
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"
"net/http"
"os"
"time"
"git.nutfactory.org/hoernschen/Matrix/config"
"git.nutfactory.org/hoernschen/Matrix/entities/device"
@ -14,6 +15,7 @@ import (
"git.nutfactory.org/hoernschen/Matrix/entities/user"
"git.nutfactory.org/hoernschen/Matrix/utils/database"
"git.nutfactory.org/hoernschen/Matrix/utils/router"
"github.com/lestrrat-go/backoff"
)
var keyPath = "./ssl.key"
@ -25,6 +27,7 @@ var routes = router.Routes{
router.Route{"ResolveServerName", "GET", "/.well-known/matrix/server", general.ResolveServerName},
router.Route{"GetServerImplementation", "GET", "/_matrix/federation/v1/version", general.GetServerImplementation},
router.Route{"Reset", "GET", "/reset", general.Reset},
router.Route{"SetParams", "GET", "/setparams", general.SetParams},
// Keys
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)
os.Remove("sqlite.db")
config.BackoffPolicy = backoff.NewExponential(
backoff.WithInterval(500*time.Millisecond),
backoff.WithMaxRetries(16),
)
if err := database.InitDB("sqlite.db"); err != nil {
log.Fatal(err)
}
defer database.DB.Close()
// TODO: Set Default Config Params here
config.HttpString = "https"
config.SetDefaultParams()
router := router.NewRouter(routes)
// TODO: Serve on Port 443 and 80 without Redirect
httpErr := http.ListenAndServeTLS(":443", certPath, keyPath, router)
if httpErr != nil {
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 (
"database/sql"
"fmt"
"log"
_ "github.com/mattn/go-sqlite3"
)
@ -11,7 +10,6 @@ import (
var DB *sql.DB
func InitDB(filepath string) (err error) {
log.Printf("Init DB")
DB, err = sql.Open("sqlite3", filepath)
if err != nil {
panic(err)
@ -31,7 +29,6 @@ func InitDB(filepath string) (err error) {
}
func initDeviceTable() (err error) {
log.Printf("Init Device Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS device (
id TEXT PRIMARY KEY,
name TEXT,
@ -43,47 +40,10 @@ func initDeviceTable() (err error) {
}
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
}
func initKeyTable() (err error) {
log.Printf("Init Key Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS key (
id TEXT PRIMARY KEY,
type TEXT,
@ -94,46 +54,11 @@ func initKeyTable() (err error) {
return
}
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
}
func initEventTable() (err error) {
log.Printf("Init Event Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS event (
id TEXT PRIMARY KEY,
roomId TEXT,
@ -172,60 +97,11 @@ func initEventTable() (err error) {
return
}
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
}
func initRoomTable() (err error) {
log.Printf("Init Room Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS room (
id TEXT PRIMARY KEY,
version TEXT,
@ -249,61 +125,11 @@ func initRoomTable() (err error) {
return
}
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
}
func initTransactionTable() (err error) {
log.Printf("Init Transaction Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS txn (
id TEXT PRIMARY KEY,
origin TEXT,
@ -314,40 +140,10 @@ func initTransactionTable() (err error) {
}
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
}
func initUserTable() (err error) {
log.Printf("Init User Table")
statement, err := DB.Prepare(`CREATE TABLE IF NOT EXISTS user (
id TEXT PRIMARY KEY,
name TEXT,
@ -358,36 +154,6 @@ func initUserTable() (err error) {
}
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
}

View file

@ -49,17 +49,26 @@ func GenerateKeyPair() (publicKey ed25519.PublicKey, privateKey ed25519.PrivateK
return
}
func Sign(message []byte) []byte {
return ed25519.Sign(config.PrivateKey, message)
func Sign(message []byte) string {
signatureBytes := ed25519.Sign(config.PrivateKey, message)
return base64.RawStdEncoding.EncodeToString(signatureBytes)
}
func SignContent(content []byte) (signatures map[string]map[string]string) {
signatures = make(map[string]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
}
func VerifySignature(publicKey []byte, message []byte, signature []byte) bool {
return ed25519.Verify(publicKey, message, signature)
func VerifySignature(publicKey []byte, message []byte, signature string) bool {
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
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
@ -32,7 +32,10 @@ func CheckRequest(r *http.Request) (response *ErrorResponse) {
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")
if authHeader == "" || !strings.Contains(authHeader, "X-Matrix") {
response = &ErrorResponse{ErrorMessage: "Missing Authorization Header"}
@ -40,15 +43,12 @@ func CheckAuthHeader(r *http.Request) (response *ErrorResponse) {
}
keys := strings.Split(authHeader, ",")
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"}
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)
buf := new(bytes.Buffer)
buf.ReadFrom(r.Body)
content := buf.String()
requestSummary := RequestSummary{
Method: r.Method,
Uri: r.RequestURI,
@ -61,7 +61,7 @@ func CheckAuthHeader(r *http.Request) (response *ErrorResponse) {
response = &ErrorResponse{ErrorMessage: "Error Creating Auth JSON String"}
return
}
correct := VerifySignature([]byte(key), requestSummaryString, []byte(signature))
correct := VerifySignature([]byte(key), requestSummaryString, signature)
if !correct {
response = &ErrorResponse{ErrorMessage: "Signature in Auth Header is incorrect"}
return
@ -81,7 +81,7 @@ func CreateAuthHeader(method string, uri string, destination string, content str
if err != nil {
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
}
@ -98,6 +98,19 @@ func GetAccessToken(r *http.Request) (token string, response *ErrorResponse) {
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 {
var js string
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)
}