diff options
Diffstat (limited to 'server/server.go')
-rw-r--r-- | server/server.go | 108 |
1 files changed, 103 insertions, 5 deletions
diff --git a/server/server.go b/server/server.go index 709888b..e84b4e0 100644 --- a/server/server.go +++ b/server/server.go @@ -1,17 +1,115 @@ package main import ( + "crypto/sha256" + "encoding/hex" + "flag" "fmt" - "html" + "io" "log" "net/http" + "sort" + "strings" + "sync" ) -func handler(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path)) +var mu sync.Mutex +var me string +var hashToDomain map[string]string +var peerHashes []string +var kvstore map[string]string + +func sha256sum(s string) string { + // Get the sha256sum of string as a hex string + b := sha256.Sum256([]byte(s)) + return hex.EncodeToString(b[:]) +} + +func addPeer(peer string) error { + // Try to peer with another server + peerHash := sha256sum(peer) + // Check if already peered + mu.Lock() + _, ok := hashToDomain[peerHash] + mu.Unlock() + if ok { + return nil + } + mu.Lock() + hashToDomain[peerHash] = peer + mu.Unlock() + + // Try request to peer + log.Printf("%s trying to peer with %s", me, peer) + resp, err := http.Get(peer + "/peer?peer=" + me) + if err != nil { + // Request failed, delete peer + mu.Lock() + delete(hashToDomain, peerHash) + mu.Unlock() + return err + } + + log.Printf("%s successfully peered with %s", me, peer) + mu.Lock() + peerHashes = append(peerHashes, peerHash) + sort.Sort(sort.StringSlice(peerHashes)) + mu.Unlock() + // Read response body + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + // Try adding all peers of this peer + newPeers := strings.Split(string(body), "\n") + for _, newPeer := range newPeers[:len(newPeers)-1] { + go addPeer(newPeer) + } + return nil +} + +func peerHandler(w http.ResponseWriter, r *http.Request) { + // Handle incoming peer requests + r.ParseForm() + peer := r.Form.Get("peer") + if peer == "" { + w.WriteHeader(http.StatusBadRequest) + return + } + go addPeer(peer) + for _, p := range hashToDomain { + fmt.Fprintf(w, "%s\n", p) + } +} + +func getHandler(w http.ResponseWriter, r *http.Request) { + +} + +func setHandler(w http.ResponseWriter, r *http.Request) { + } func main() { - http.HandleFunc("/", handler) - log.Fatal(http.ListenAndServe(":8080", nil)) + bindAddr := flag.String("b", ":4200", "bind address") + domain := flag.String("d", "http://localhost:4200", "full domain name") + peer := flag.String("i", "", "initial peer") + flag.Parse() + + log.Printf("Starting %s %s %s", *bindAddr, *domain, *peer) + + // Record myself + me = *domain + peerHashes = append(peerHashes, sha256sum(me)) + hashToDomain = map[string]string{peerHashes[0]: me} + + if *peer != "" { + go addPeer(*peer) + } + + http.HandleFunc("/peer", peerHandler) + http.HandleFunc("/get", getHandler) + http.HandleFunc("/set", setHandler) + log.Fatal(http.ListenAndServe(*bindAddr, nil)) } |