laserproxy: init
Change-Id: I1900be6eea2d702548279176d796c58c34952dc8
diff --git a/hswaw/laserproxy/proxy.go b/hswaw/laserproxy/proxy.go
new file mode 100644
index 0000000..21f9399
--- /dev/null
+++ b/hswaw/laserproxy/proxy.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+ "context"
+ "net"
+ "strings"
+
+ "github.com/golang/glog"
+)
+
+type packetFrom struct {
+ addr net.Addr
+ data []byte
+}
+
+func (s *service) runProxy(ctx context.Context, updates chan *lockUpdate, laserAddr net.Addr, laserNet, clientNet net.PacketConn) {
+ glog.Infof("Proxy starting... (laser: %v, laser network: %v, client network: %v)", laserAddr, laserNet, clientNet)
+
+
+ pipe := func(conn net.PacketConn, C chan *packetFrom) {
+ for {
+ buf := make([]byte, 1500)
+ n, addr, err := conn.ReadFrom(buf)
+ if err != nil {
+ glog.Errorf("pipe failed: %v", err)
+ }
+ C <- &packetFrom{ addr, buf[:n] }
+ }
+ }
+
+ laserC := make(chan *packetFrom)
+ go pipe(laserNet, laserC)
+ clientC := make(chan *packetFrom)
+ go pipe(clientNet, clientC)
+
+ var allowedClient string
+ var curClient *net.Addr
+ for {
+ select {
+ case <-ctx.Done():
+ err := ctx.Err()
+ glog.Errorf("Proxy stopped: %v", err)
+ return
+ case u := <-updates:
+ allowedClient = u.addr
+ glog.Infof("New allowed client: %q", allowedClient)
+ case p := <-laserC:
+ s.lockCtrl <- &lockCtrl{
+ bump: &lockCtrlBump{},
+ }
+ if curClient == nil {
+ glog.Warningf("Packet from laser without client connected, dropping.")
+ break
+ }
+ clientNet.WriteTo(p.data, *curClient)
+ case p := <-clientC:
+ s.lockCtrl <- &lockCtrl{
+ bump: &lockCtrlBump{},
+ }
+ if strings.Split(p.addr.String(), ":")[0] == allowedClient {
+ curClient = &p.addr
+ laserNet.WriteTo(p.data, laserAddr)
+ } else {
+ glog.Infof("Rejecting packet from %s", p.addr.String())
+ }
+ }
+ }
+}
+