Skip to content

Commit

Permalink
Update metrics package and plugin addresses to use structs API.
Browse files Browse the repository at this point in the history
This change updates the metrics package and plugin addresses to use structs API, replacing the previous api.NodeStatus and api.ClientStatus with structs.NodeStatus and structs.ClientStatus respectively. The file config/config.go is also modified to set the addresses of nodes, clients, bulletin board, and metrics. Additionally, the function AddressToName is introduced to map addresses to names.
  • Loading branch information
HannahMarsh committed Jun 27, 2024
1 parent ec56c80 commit 5a69ffb
Show file tree
Hide file tree
Showing 22 changed files with 853 additions and 208 deletions.
18 changes: 9 additions & 9 deletions cmd/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"fmt"
pl "github.com/HannahMarsh/PrettyLogger"
"github.com/HannahMarsh/pi_t-experiment/config"
"github.com/HannahMarsh/pi_t-experiment/internal/api"
"github.com/HannahMarsh/pi_t-experiment/internal/api/structs"
_ "github.com/lib/pq"
"go.uber.org/automaxprocs/maxprocs"
"golang.org/x/exp/slog"
Expand Down Expand Up @@ -82,16 +82,16 @@ func main() {
}

type Data struct {
Clients map[string]api.ClientStatus
Clients map[string]structs.ClientStatus
Messages []Message
Nodes map[string]api.NodeStatus
Nodes map[string]structs.NodeStatus
mu sync.RWMutex
}

type Message struct {
From string
To string
RoutingPath []api.PublicNodeApi
RoutingPath []structs.PublicNodeApi
Msg string
TimeSent string
TimeReceived string
Expand All @@ -100,9 +100,9 @@ type Message struct {

var (
data Data = Data{
Clients: make(map[string]api.ClientStatus),
Clients: make(map[string]structs.ClientStatus),
Messages: make([]Message, 0),
Nodes: make(map[string]api.NodeStatus),
Nodes: make(map[string]structs.NodeStatus),
}
)

Expand All @@ -120,7 +120,7 @@ func serveData(w http.ResponseWriter, r *http.Request) {
slog.Error("failed to get client status", err)
} else {
defer resp.Body.Close()
var status api.ClientStatus
var status structs.ClientStatus
if err = json.NewDecoder(resp.Body).Decode(&status); err != nil {
slog.Error("failed to decode client status", err)
} else {
Expand All @@ -136,7 +136,7 @@ func serveData(w http.ResponseWriter, r *http.Request) {
slog.Error("failed to get client status", err)
} else {
defer resp.Body.Close()
var status api.NodeStatus
var status structs.NodeStatus
if err = json.NewDecoder(resp.Body).Decode(&status); err != nil {
slog.Error("failed to decode client status", err)
} else {
Expand Down Expand Up @@ -214,7 +214,7 @@ func serveData(w http.ResponseWriter, r *http.Request) {
m[mstr] = Message{
From: received.Message.From,
To: received.Message.To,
RoutingPath: make([]api.PublicNodeApi, 0),
RoutingPath: make([]structs.PublicNodeApi, 0),
Msg: received.Message.Msg,
TimeSent: "not sent",
TimeReceived: received.TimeReceived.Format("2006-01-02 15:04:05"),
Expand Down
98 changes: 87 additions & 11 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,42 @@ package config

import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"sync"

"github.com/HannahMarsh/PrettyLogger"
"github.com/ilyakaznacheev/cleanenv"
)

type BulletinBoard struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Address string
}

type Node struct {
ID int `yaml:"id"`
Host string `yaml:"host"`
Port int `yaml:"port"`
IsMixer bool `yaml:"is_mixer"`
Address string
IsMixer bool `yaml:"is_mixer"`
}

type Client struct {
ID int `yaml:"id"`
Host string `yaml:"host"`
Port int `yaml:"port"`
ID int `yaml:"id"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Address string
}

type Metrics struct {
Host string `yaml:"host"`
Port int `yaml:"port"`
Host string `yaml:"host"`
Port int `yaml:"port"`
Address string
}

type Config struct {
Expand All @@ -49,6 +58,7 @@ type Config struct {
var GlobalConfig *Config
var GlobalCtx context.Context
var GlobalCancel context.CancelFunc
var Names sync.Map

func InitGlobal() error {
GlobalCtx, GlobalCancel = context.WithCancel(context.Background())
Expand All @@ -58,10 +68,76 @@ func InitGlobal() error {
if dir, err := os.Getwd(); err != nil {
return PrettyLogger.WrapError(err, "config.NewConfig(): global config error")
} else if err2 := cleanenv.ReadConfig(dir+"/config/config.yml", GlobalConfig); err2 != nil {
return PrettyLogger.WrapError(err2, "config.NewConfig(): global config error")
// Get the absolute path of the current file
_, currentFile, _, ok := runtime.Caller(0)
if !ok {
return PrettyLogger.NewError("Failed to get current file path")
}
currentDir := filepath.Dir(currentFile)
configFilePath := filepath.Join(currentDir, "/config.yml")
if err3 := cleanenv.ReadConfig(configFilePath, GlobalConfig); err3 != nil {
return PrettyLogger.WrapError(err3, "config.NewConfig(): global config error")
}
} else if err3 := cleanenv.ReadEnv(GlobalConfig); err3 != nil {
return PrettyLogger.WrapError(err3, "config.NewConfig(): global config error")
} else {
return nil
}
// Update node addresses
for i := range GlobalConfig.Nodes {
GlobalConfig.Nodes[i].Address = fmt.Sprintf("http://%s:%d", GlobalConfig.Nodes[i].Host, GlobalConfig.Nodes[i].Port)
}

// Update client addresses
for i := range GlobalConfig.Clients {
GlobalConfig.Clients[i].Address = fmt.Sprintf("http://%s:%d", GlobalConfig.Clients[i].Host, GlobalConfig.Clients[i].Port)
}

GlobalConfig.BulletinBoard.Address = fmt.Sprintf("http://%s:%d", GlobalConfig.BulletinBoard.Host, GlobalConfig.BulletinBoard.Port)
GlobalConfig.Metrics.Address = fmt.Sprintf("http://%s:%d", GlobalConfig.Metrics.Host, GlobalConfig.Metrics.Port)
return nil
}

func HostPortToName(host string, port int) string {
return AddressToName(fmt.Sprintf("http://%s:%d", host, port))
}

var PurpleColor = "\033[35m"
var OrangeColor = "\033[33m"
var ResetColor = "\033[0m"

func AddressToName(address string) string {
if name, ok := Names.Load(address); ok {
return name.(string)
}
if strings.Count(address, "/") > 2 {
spl := strings.Split(address, "/")
address = spl[0] + "//" + spl[1]
}
if name, ok := Names.Load(address); ok {
return name.(string)
}
for _, node := range GlobalConfig.Nodes {
if address == node.Address {
name := fmt.Sprintf("%sNode %d%s", PurpleColor, node.ID, ResetColor)
Names.Store(address, name)
return name
}
}
for _, client := range GlobalConfig.Clients {
if address == client.Address {
name := fmt.Sprintf("%sClient %d%s", OrangeColor, client.ID, ResetColor)
Names.Store(address, name)
return name
}
}
if address == GlobalConfig.BulletinBoard.Address {
name := "Bulletin Board"
Names.Store(address, name)
return name
}
if address == GlobalConfig.Metrics.Address {
name := "Metrics"
Names.Store(address, name)
return name
}
return address
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.21
toolchain go1.21.2

require (
github.com/HannahMarsh/PrettyLogger v0.0.0-20240624195816-fafd56cd6e16
github.com/HannahMarsh/PrettyLogger v0.0.0-20240627161104-d84de9582a09
github.com/emirpasic/gods v1.18.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.12.0
github.com/ilyakaznacheev/cleanenv v1.3.0
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/HannahMarsh/PrettyLogger v0.0.0-20240624195816-fafd56cd6e16 h1:d3Imt2sMb76EBrqho99go85ttWRR/fzMcV/poScQzsI=
github.com/HannahMarsh/PrettyLogger v0.0.0-20240624195816-fafd56cd6e16/go.mod h1:DnsFnxjM3dXHLKhtLJR4TGv7iTRhiLSP+AdZ1RWB4ew=
github.com/HannahMarsh/PrettyLogger v0.0.0-20240627135600-dc396d401402 h1:LRMGemJd+x1yNY84Y8Kgtv6rUo1h65j5q2MnCgF2kD0=
github.com/HannahMarsh/PrettyLogger v0.0.0-20240627135600-dc396d401402/go.mod h1:DnsFnxjM3dXHLKhtLJR4TGv7iTRhiLSP+AdZ1RWB4ew=
github.com/HannahMarsh/PrettyLogger v0.0.0-20240627161104-d84de9582a09 h1:lP0kxZltSpOzYEy577fvip+2NpiXhl9zK19rO/VZtYY=
github.com/HannahMarsh/PrettyLogger v0.0.0-20240627161104-d84de9582a09/go.mod h1:DnsFnxjM3dXHLKhtLJR4TGv7iTRhiLSP+AdZ1RWB4ew=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down
108 changes: 108 additions & 0 deletions internal/api/api_functions/functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package api_functions

import (
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
pl "github.com/HannahMarsh/PrettyLogger"
"github.com/HannahMarsh/pi_t-experiment/config"
"github.com/HannahMarsh/pi_t-experiment/internal/api/structs"
"github.com/HannahMarsh/pi_t-experiment/pkg/utils"
"golang.org/x/exp/slog"
"io"
"net/http"
"time"
)

// sendOnion sends an onion to the specified address with compression and timeout
func SendOnion(to, from, onionStr string) error {
slog.Info(pl.GetFuncName()+": Sending onion...", "from", config.AddressToName(from), "to", config.AddressToName(to))
url := fmt.Sprintf("%s/receive", to)

data, err := base64.StdEncoding.DecodeString(onionStr)
if err != nil {
return pl.WrapError(err, "%s: failed to decode onion string", pl.GetFuncName())
}

//beforeSize := len(data)

compressedData, err := utils.Compress(data)
if err != nil {
return pl.WrapError(err, "%s: failed to compress onion", pl.GetFuncName())
}

//afterSize := len(compressedData)
//slog.Info(pl.GetFuncName(), "before", beforeSize, "after", afterSize, "Saved", fmt.Sprintf("%.2f%%", 100-float64(afterSize)/float64(beforeSize)*100))

encodeToString := base64.StdEncoding.EncodeToString(compressedData)
onion := structs.OnionApi{
To: to,
From: from,
Onion: encodeToString,
}

payload, err := json.Marshal(onion)
if err != nil {
return pl.WrapError(err, "%s: failed to marshal onion", pl.GetFuncName())
}

client := &http.Client{
Timeout: 10 * time.Second, // Set timeout
}

//slog.Info(pl.GetFuncName() + ": payload size: " + fmt.Sprintf("%d", len(payload)))

resp, err := client.Post(url, "application/json", bytes.NewBuffer(payload))
if err != nil {
return pl.WrapError(err, "%s: failed to send POST request with onion to first mixer", pl.GetFuncName())
}

defer func(Body io.ReadCloser) {
if err = Body.Close(); err != nil {
slog.Error("Error closing response body", err)
}
}(resp.Body)

if resp.StatusCode != http.StatusOK {
return pl.NewError("%s: failed to send to first node(url=%s), status code: %d, status: %s", pl.GetFuncName(), url, resp.StatusCode, resp.Status)
}

slog.Info("✅ Successfully sent onion. ", "from", config.AddressToName(from), "to", config.AddressToName(to))
return nil
}

func HandleReceiveOnion(w http.ResponseWriter, r *http.Request, receiveFunction func(string) error) {
var o structs.OnionApi
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "unable to read body", http.StatusInternalServerError)
return
}
if err := json.Unmarshal(body, &o); err != nil {
slog.Error("Error decoding onion", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

data, err := base64.StdEncoding.DecodeString(o.Onion)
if err != nil {
slog.Error("Error decoding onion", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

decompressedData, err := utils.Decompress(data)
if err != nil {
slog.Error("Error decompressing data", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
onionString := base64.StdEncoding.EncodeToString(decompressedData)
if err = receiveFunction(onionString); err != nil {
slog.Error("Error receiving onion", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
}
Loading

0 comments on commit 5a69ffb

Please sign in to comment.