Hochwasser/rpc/ran.go

134 lines
2.9 KiB
Go
Raw Normal View History

2020-02-11 14:46:58 +01:00
package rpc
import (
2020-02-12 13:55:04 +01:00
// "io"
"bufio"
2020-02-11 14:46:58 +01:00
"fmt"
"image"
"log"
"net"
"net/rpc"
2020-02-12 13:55:04 +01:00
"os"
"os/signal"
"strings"
2020-02-11 14:46:58 +01:00
"time"
)
2020-02-12 11:20:15 +01:00
type Rán struct {
clients []*rpc.Client
task FlutTask
}
func SummonRán(address string) *Rán {
r := new(Rán)
2020-02-11 14:46:58 +01:00
l, err := net.Listen("tcp", address)
if err != nil {
log.Fatal(err)
}
fmt.Printf("[rán] rpc server listening on %s\n", l.Addr())
2020-02-12 11:20:15 +01:00
// serve tcp port, handshake
2020-02-11 14:46:58 +01:00
go func() {
for {
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
client := rpc.NewClient(conn)
2020-02-12 11:20:15 +01:00
r.clients = append(r.clients, client)
fmt.Printf("[rán] client connected (%v). current clients: %v\n",
conn.RemoteAddr(), len(r.clients))
2020-02-11 14:46:58 +01:00
2020-02-12 11:20:15 +01:00
if (r.task != FlutTask{}) {
ack := FlutAck{}
err = client.Call("Hevring.Flut", r.task, &ack)
if err != nil || !ack.Ok {
log.Printf("[rán] client didn't accept task")
}
2020-02-11 14:46:58 +01:00
}
}
}()
// poll clients
go func() {
for {
2020-02-12 11:20:15 +01:00
time.Sleep(100 * time.Millisecond)
2020-02-11 14:46:58 +01:00
var clients []*rpc.Client
2020-02-12 11:20:15 +01:00
for _, c := range r.clients {
2020-02-11 14:46:58 +01:00
status := FlutAck{}
2020-02-12 11:20:15 +01:00
err3 := c.Call("Hevring.Status", 0, &status)
if err3 == nil || status.Ok {
2020-02-11 14:46:58 +01:00
clients = append(clients, c)
}
}
2020-02-12 11:20:15 +01:00
if len(r.clients) != len(clients) {
fmt.Printf("[rán] client disconnected. current clients: %v\n", len(clients))
}
r.clients = clients
2020-02-11 14:46:58 +01:00
}
}()
2020-02-12 13:55:04 +01:00
// REPL to change tasks without loosing clients
go func() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input := strings.Split(scanner.Text(), " ")
cmd := strings.ToLower(input[0])
args := input[1:]
if cmd == "stop" {
for _, c := range r.clients {
ack := FlutAck{}
c.Call("Hevring.Stop", 0, &ack) // @speed: async
}
} else if cmd == "img" && len(args) > 0 {
// // @incomplete
// path := args[0]
// img := readImage(path)
// offset := image.Pt(0, 0)
// if len(args) == 3 {
// x := strconv.Atoi(args[1])
// y := strconv.Atoi(args[2])
// offset = image.Pt(x, y)
// }
// task := FlutTask{}
}
}
}()
// kill clients on exit
go func() {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt)
for {
<-sigChan
for _, c := range r.clients {
ack := FlutAck{}
c.Call("Hevring.Die", 0, &ack) // @speed: async
}
os.Exit(0) // @bug :cleanExit
}
}()
2020-02-11 14:46:58 +01:00
2020-02-12 11:20:15 +01:00
return r
2020-02-11 14:46:58 +01:00
}
2020-02-12 11:20:15 +01:00
func (r *Rán) SetTask(img image.Image, offset image.Point, address string, maxConns int) {
// @incomplete: smart task creation:
// fetch server state & sample foreign activity in image regions. assign
// subregions to clients (per connection), considering their bandwidth.
// @bug :imageType
r.task = FlutTask{address, maxConns, img.(*image.NRGBA), offset, true}
for _, c := range r.clients {
ack := FlutAck{}
// @speed: should send tasks async
err := c.Call("Hevring.Flut", r.task, &ack)
if err != nil || !ack.Ok {
log.Printf("[rán] client didn't accept task")
}
}
2020-02-11 14:46:58 +01:00
}