aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorAnthony Wang2023-05-10 13:44:15 -0400
committerAnthony Wang2023-05-10 13:44:15 -0400
commit6e8bcca87e23645cc6a471bd43b61f7b7a0b9521 (patch)
tree8456614c4d6a6284a022abd31a43373bb2d58e5d /server
parentf2414e8a6b6276825efcc2b7132683ce15289537 (diff)
Implement server peering
Diffstat (limited to 'server')
-rw-r--r--server/server.go108
-rwxr-xr-xserver/test.sh10
2 files changed, 113 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))
}
diff --git a/server/test.sh b/server/test.sh
new file mode 100755
index 0000000..8ca1d42
--- /dev/null
+++ b/server/test.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+trap "kill 0" EXIT
+go build
+./server -b :4200 -d http://localhost:4200 &
+for i in $(seq 1 9)
+do
+ sleep 0.1
+ ./server -b :420$i -d http://localhost:420$i -i http://localhost:420$((i-1)) &
+done
+wait