diff --git a/init.go b/init.go index b3129a4..873b077 100644 --- a/init.go +++ b/init.go @@ -2,17 +2,22 @@ package main import ( "bufio" + "crypto/rand" + "encoding/base64" "encoding/json" "fmt" "log" "os" "strconv" + "strings" ) // Configuration structure type Config struct { - Port int - OpenSearch OpenSearchConfig + Port int + ConnectionCode string + Peers []string + OpenSearch OpenSearchConfig } type OpenSearchConfig struct { @@ -37,6 +42,9 @@ func main() { return } + // This is stupid + loadNodeConfig() + // Start the main application runServer() } @@ -74,6 +82,21 @@ func createConfig() error { if domain != "\n" { config.OpenSearch.Domain = domain[:len(domain)-1] } + + fmt.Print("Do you want to connect to other nodes? (yes/no): ") + connectNodes, _ := reader.ReadString('\n') + if strings.TrimSpace(connectNodes) == "yes" { + fmt.Println("Enter peer addresses (comma separated, e.g., http://localhost:5000,http://localhost:5001): ") + peersStr, _ := reader.ReadString('\n') + if peersStr != "\n" { + config.Peers = strings.Split(strings.TrimSpace(peersStr), ",") + } + } + } + + if config.ConnectionCode == "" { + config.ConnectionCode = generateStrongRandomString(32) + fmt.Printf("Generated connection code: %s\n", config.ConnectionCode) } saveConfig(config) @@ -114,3 +137,12 @@ func loadConfig() Config { return config } + +func generateStrongRandomString(length int) string { + bytes := make([]byte, length) + _, err := rand.Read(bytes) + if err != nil { + log.Fatalf("Error generating random string: %v", err) + } + return base64.URLEncoding.EncodeToString(bytes)[:length] +} diff --git a/main.go b/main.go index 98c8eb3..f05108a 100644 --- a/main.go +++ b/main.go @@ -140,9 +140,12 @@ func runServer() { config := loadConfig() generateOpenSearchXML(config) + fmt.Printf("Server is listening on http://localhost:%d\n", config.Port) + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", config.Port), nil)) + // Start node communication client go startNodeClient(peers) - fmt.Printf("Server is listening on http://localhost:%d\n", config.Port) - log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", config.Port), nil)) + // Start automatic update checker + go checkForUpdates() } diff --git a/node-update.go b/node-update.go new file mode 100644 index 0000000..e67a160 --- /dev/null +++ b/node-update.go @@ -0,0 +1,23 @@ +package main + +import ( + "fmt" + "log" + "time" +) + +// Function to sync updates across all nodes +func nodeUpdateSync() { + fmt.Println("Syncing updates across all nodes...") + for _, peer := range peers { + fmt.Printf("Notifying node %s about update...\n", peer) + err := sendMessage(peer, connCode, "update", "Start update process") + if err != nil { + log.Printf("Failed to notify node %s: %v\n", peer, err) + continue + } + fmt.Printf("Node %s notified. Waiting for it to update...\n", peer) + time.Sleep(30 * time.Second) // Adjust sleep time as needed to allow for updates + } + fmt.Println("All nodes have been updated.") +} diff --git a/node.go b/node.go index afe9f1d..5c04e18 100644 --- a/node.go +++ b/node.go @@ -1,21 +1,32 @@ package main import ( + "bytes" + "encoding/json" "fmt" "io/ioutil" "net/http" - "strings" "sync" "time" ) -const ( - connCode = "secretcode123" - testMsg = "This is a test message" +var ( + connCode string + peers []string + connCodeMutex sync.Mutex ) -var connCodeMutex sync.Mutex -var peers = []string{"localhost:50002", "localhost:5000"} // Example peer addresses +type Message struct { + ID string `json:"id"` + Type string `json:"type"` + Content string `json:"content"` +} + +func loadNodeConfig() { + config := loadConfig() + connCode = config.ConnectionCode + peers = config.Peers +} func handleNodeRequest(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { @@ -33,55 +44,78 @@ func handleNodeRequest(w http.ResponseWriter, r *http.Request) { } defer r.Body.Close() - receivedCode := strings.TrimSpace(string(body)) + var msg Message + if err := json.Unmarshal(body, &msg); err != nil { + http.Error(w, "Error parsing JSON", http.StatusBadRequest) + return + } - if receivedCode != connCode { + if msg.ID != connCode { http.Error(w, "Authentication failed", http.StatusUnauthorized) return } - fmt.Println("Authentication successful") - fmt.Fprintln(w, testMsg) + interpretMessage(msg) + fmt.Fprintln(w, "Message received") +} + +func interpretMessage(msg Message) { + switch msg.Type { + case "test": + fmt.Println("Received test message:", msg.Content) + case "get-version": + fmt.Println("Received get-version message") + // Handle get-version logic here + case "update": + fmt.Println("Received update message:", msg.Content) + // Handle update logic here + go update() + default: + fmt.Println("Received unknown message type:", msg.Type) + } +} + +func sendMessage(address, id, msgType, content string) error { + msg := Message{ + ID: id, + Type: msgType, + Content: content, + } + msgBytes, err := json.Marshal(msg) + if err != nil { + return err + } + + req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("%s/node", address), bytes.NewBuffer(msgBytes)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("failed to send message: %s", body) + } + + return nil } func startNodeClient(addresses []string) { for _, address := range addresses { go func(addr string) { for { - url := fmt.Sprintf("http://%s/node", addr) - req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(connCode)) + err := sendMessage(addr, connCode, "test", "This is a test message") if err != nil { - fmt.Println("Error creating request:", err) - time.Sleep(5 * time.Second) + fmt.Println("Error sending test message to", addr, ":", err) continue } - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - fmt.Println("Error connecting to", addr, ":", err) - time.Sleep(5 * time.Second) - continue - } - - if resp.StatusCode != http.StatusOK { - fmt.Println("Authentication failed:", resp.Status) - resp.Body.Close() - time.Sleep(5 * time.Second) - continue - } - - body, err := ioutil.ReadAll(resp.Body) - if err != nil { - fmt.Println("Error reading response:", err) - resp.Body.Close() - time.Sleep(5 * time.Second) - continue - } - resp.Body.Close() - - testMsg := strings.TrimSpace(string(body)) - fmt.Println("Received test message from", addr, ":", testMsg) time.Sleep(10 * time.Second) } }(address) diff --git a/update.go b/update.go new file mode 100644 index 0000000..3e31ba0 --- /dev/null +++ b/update.go @@ -0,0 +1,52 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + "time" +) + +// Function to check for updates and restart the server if an update is found +func checkForUpdates() { + repoURL := "https://weforgecode.xyz/Spitfire/Search.git" + localDir := "." // Assume the repository is cloned in the current directory + + for { + err := gitPull(repoURL, localDir) + if err != nil { + fmt.Println("Error checking for updates:", err) + time.Sleep(10 * time.Minute) + continue + } + + fmt.Println("Update found. Syncing updates...") + nodeUpdateSync() + + fmt.Println("Restarting server to apply updates...") + update() + time.Sleep(10 * time.Minute) + } +} + +// Function to pull updates from the Git repository +func gitPull(repoURL, localDir string) error { + cmd := exec.Command("git", "-C", localDir, "pull", repoURL) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + return cmd.Run() +} + +// Function to download updates and restart the server +func update() { + cmd := exec.Command("sh", "run.sh") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + err := cmd.Start() + if err != nil { + fmt.Println("Error starting the server:", err) + return + } + + os.Exit(0) +}