638 lines
16 KiB
Go
638 lines
16 KiB
Go
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 = false
|
|
|
|
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",
|
|
},
|
|
},
|
|
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",
|
|
},
|
|
},
|
|
map[string][]string{
|
|
"localhost": []string{
|
|
"user1",
|
|
"user2",
|
|
"user3",
|
|
"user4",
|
|
},
|
|
},
|
|
}
|
|
|
|
/*
|
|
var servers = []string{
|
|
"143.93.38.207",
|
|
"143.93.38.208",
|
|
"143.93.38.209",
|
|
}
|
|
*/
|
|
|
|
var servers = []string{
|
|
"localhost",
|
|
}
|
|
|
|
var systemParams = []SystemParams{
|
|
SystemParams{
|
|
Id: "111111111",
|
|
BytesToSend: 280,
|
|
MessagesPerSecond: 1.0,
|
|
Distribution: users[3],
|
|
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)
|
|
}
|