summaryrefslogtreecommitdiffstats
path: root/server/remote.go
diff options
context:
space:
mode:
Diffstat (limited to 'server/remote.go')
-rw-r--r--server/remote.go112
1 files changed, 112 insertions, 0 deletions
diff --git a/server/remote.go b/server/remote.go
new file mode 100644
index 0000000..2449511
--- /dev/null
+++ b/server/remote.go
@@ -0,0 +1,112 @@
+package server
+
+import (
+ "log"
+ "net"
+
+ "go.rctt.net/solec/core"
+)
+
+type RemoteServer struct {
+ Name string
+ Conn net.Conn
+}
+
+func NewRemoteServer(name string, conn net.Conn) RemoteServer {
+ return RemoteServer{name, conn}
+}
+
+func (s *Server) handleServerConn(conn net.Conn) {
+ defer conn.Close()
+
+ name, err := s.performServerAuth(conn)
+ if err != nil {
+ log.Println("server auth error:", err)
+ return
+ }
+
+ s.serversMu.RLock()
+ if _, ok := s.servers[name]; ok {
+ log.Println("server already connected")
+ return
+ }
+ s.serversMu.RUnlock()
+
+ rs := NewRemoteServer(name, conn)
+ s.serversMu.Lock()
+ s.servers[name] = rs
+ s.serversMu.Unlock()
+ log.Println("connection from server:", name)
+
+ defer func() {
+ s.serversMu.Lock()
+ log.Println("server disconnected: ", rs.Name)
+ delete(s.servers, rs.Name)
+ s.serversMu.Unlock()
+ }()
+
+ if err := s.readInput(conn); err != nil {
+ log.Println(err)
+ }
+}
+
+func (s *Server) performServerAuth(conn net.Conn) (string, error) {
+ payload, err := core.Decode(conn)
+ if err != nil {
+ return "", err
+ }
+ auth, ok := payload.(core.ServerAuth)
+ if !ok {
+ return "", core.ErrUnexpectedPayloadType
+ }
+
+ if err := core.Send(conn, core.Success{}); err != nil {
+ return "", err
+ }
+
+ return auth.Name, nil
+}
+
+func (s *Server) getRemote(name string) (RemoteServer, error) {
+ s.serversMu.RLock()
+ remote, ok := s.servers[name]
+ s.serversMu.RUnlock()
+
+ if ok {
+ return remote, nil
+ }
+
+ conn, err := s.initRemoteConn(name)
+ if err != nil {
+ return RemoteServer{}, err
+ }
+
+ rs := NewRemoteServer(name, conn)
+ s.serversMu.Lock()
+ s.servers[name] = rs
+ s.serversMu.Unlock()
+ log.Println("connected to server:", name)
+
+ return rs, nil
+}
+
+func (s *Server) initRemoteConn(name string) (net.Conn, error) {
+ conn, err := net.Dial("tcp", name+":9999")
+ if err != nil {
+ return conn, err
+ }
+
+ hs := core.Handshake{0, 1, core.ConnTypeServer}
+ if err := core.Send(conn, hs); err != nil {
+ conn.Close()
+ return conn, err
+ }
+
+ auth := core.ServerAuth{Name: s.name}
+ if err := core.Send(conn, auth); err != nil {
+ conn.Close()
+ return conn, err
+ }
+
+ return conn, nil
+}