package main import ( "bytes" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "io/ioutil" "log" "net/http" "sync" "time" ) var ( authCode string peers []string authMutex sync.Mutex authenticated = make(map[string]bool) ) type Message struct { ID string `json:"id"` Type string `json:"type"` Content string `json:"content"` } type CrawlerConfig struct { ID string Host string Port int AuthCode string } func loadNodeConfig() { config := loadConfig() authCode = config.AuthCode // nuh uh peers = config.Peers } func handleNodeRequest(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) return } body, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusInternalServerError) return } defer r.Body.Close() var msg Message if err := json.Unmarshal(body, &msg); err != nil { http.Error(w, "Error parsing JSON", http.StatusBadRequest) return } if !isAuthenticated(msg.ID) { http.Error(w, "Authentication required", http.StatusUnauthorized) return } interpretMessage(msg) fmt.Fprintln(w, "Message received") } func handleAuth(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) return } body, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, "Error reading request body", http.StatusInternalServerError) return } defer r.Body.Close() var authRequest CrawlerConfig if err := json.Unmarshal(body, &authRequest); err != nil { http.Error(w, "Error parsing JSON", http.StatusBadRequest) return } expectedCode := GenerateRegistrationCode(authRequest.Host, authRequest.Port, authCode) if authRequest.AuthCode != expectedCode { http.Error(w, "Invalid auth code", http.StatusUnauthorized) return } authMutex.Lock() authenticated[authRequest.ID] = true authMutex.Unlock() fmt.Fprintln(w, "Authenticated successfully") } func isAuthenticated(id string) bool { authMutex.Lock() defer authMutex.Unlock() return authenticated[id] } func interpretMessage(msg Message) { switch msg.Type { case "test": fmt.Println("Received test message:", msg.Content) case "update": fmt.Println("Received update message:", msg.Content) go update() case "heartbeat": handleHeartbeat(msg.Content) case "election": handleElection(msg.Content) 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 { err := sendMessage(addr, authCode, "test", "This is a test message") if err != nil { fmt.Println("Error sending test message to", addr, ":", err) continue } time.Sleep(10 * time.Second) } }(address) } } func GenerateRegistrationCode(host string, port int, authCode string) string { data := fmt.Sprintf("%s:%d:%s", host, port, authCode) hash := sha256.Sum256([]byte(data)) return hex.EncodeToString(hash[:]) } func ParseRegistrationCode(code string, host string, port int, authCode string) (string, int, string, error) { data := fmt.Sprintf("%s:%d:%s", host, port, authCode) hash := sha256.Sum256([]byte(data)) expectedCode := hex.EncodeToString(hash[:]) log.Printf("Parsing registration code: %s", code) log.Printf("Expected registration code: %s", expectedCode) if expectedCode != code { return "", 0, "", fmt.Errorf("invalid registration code") } return host, port, authCode, nil }