removed reverese proxy from solo mode, clients can connect directly ti INDI

This commit is contained in:
dencoded 2020-02-28 15:03:02 -05:00
parent e019175669
commit 747de03bc5
2 changed files with 97 additions and 93 deletions

12
main.go
View file

@ -257,7 +257,11 @@ func main() {
Os: runtime.GOOS, Os: runtime.GOOS,
Arch: runtime.GOARCH, Arch: runtime.GOARCH,
} }
ccdDrivers := []string{}
for i, driver := range indiDrivers { for i, driver := range indiDrivers {
if driver.Family == "CCDs" {
ccdDrivers = append(ccdDrivers, driver.Binary)
}
indiHubHost.Drivers[i] = &indihub.INDIDriver{ indiHubHost.Drivers[i] = &indihub.INDIDriver{
Binary: driver.Binary, Binary: driver.Binary,
Family: driver.Family, Family: driver.Family,
@ -355,10 +359,10 @@ func main() {
log.Fatalf("Could not start agent in solo mode: %v", err) log.Fatalf("Could not start agent in solo mode: %v", err)
} }
soloProxy := solo.New( soloAgent := solo.New(
"INDI-Server Solo-mode",
indiServerAddr, indiServerAddr,
soloClient, soloClient,
ccdDrivers,
) )
go func() { go func() {
@ -373,7 +377,7 @@ func main() {
log.Println("Closing INDIHUB solo-session") log.Println("Closing INDIHUB solo-session")
// close connections to local INDI-server and to INDI client // close connections to local INDI-server and to INDI client
soloProxy.Close() soloAgent.Close()
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
@ -386,7 +390,7 @@ func main() {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
soloProxy.Start(flagSoloINDIServerAddr, regInfo.SessionID, regInfo.SessionIDPublic) soloAgent.Start(flagSoloINDIServerAddr, regInfo.SessionID, regInfo.SessionIDPublic)
}() }()
wg.Wait() wg.Wait()

View file

@ -2,10 +2,11 @@ package solo
import ( import (
"bytes" "bytes"
"io" "fmt"
"log" "log"
"net" "net"
"sync/atomic"
"github.com/clbanning/mxj"
"github.com/fatih/color" "github.com/fatih/color"
@ -14,7 +15,11 @@ import (
) )
var ( var (
getProperties = []byte("<getProperties version='1.7'/>")
enableBLOB = "<enableBLOB device='%s'>Also</enableBLOB>"
setBLOBVector = []byte("<setBLOBVector") setBLOBVector = []byte("<setBLOBVector")
defTextVector = []byte("<defTextVector")
) )
type INDIHubSoloTunnel interface { type INDIHubSoloTunnel interface {
@ -22,110 +27,109 @@ type INDIHubSoloTunnel interface {
CloseAndRecv() (*indihub.SoloSummary, error) CloseAndRecv() (*indihub.SoloSummary, error)
} }
type SoloTcpProxy struct { type Agent struct {
Name string indiServerAddr string
Addr string indiConn net.Conn
listener net.Listener tunnel INDIHubSoloTunnel
Tunnel INDIHubSoloTunnel ccdDrivers map[string]bool
shouldExit bool
connInMap map[uint32]net.Conn
connOutMap map[uint32]net.Conn
shouldExit int32
} }
func New(name string, addr string, tunnel INDIHubSoloTunnel) *SoloTcpProxy { func New(indiServerAddr string, tunnel INDIHubSoloTunnel, ccdDrivers []string) *Agent {
return &SoloTcpProxy{ ccdDriversMap := make(map[string]bool)
Name: name, for _, d := range ccdDrivers {
Addr: addr, ccdDriversMap[d] = true
Tunnel: tunnel, }
connInMap: map[uint32]net.Conn{},
connOutMap: map[uint32]net.Conn{}, return &Agent{
indiServerAddr: indiServerAddr,
tunnel: tunnel,
ccdDrivers: ccdDriversMap,
} }
} }
func (p *SoloTcpProxy) Start(addr string, sessionID uint64, sessionToken string) { func (p *Agent) Start(indiServerAddr string, sessionID uint64, sessionToken string) error {
log.Printf("Starting INDI-server for INDIHUB in solo mode on %s ...", addr) // open connection to real INDI-server
var err error var err error
p.listener, err = net.Listen("tcp", addr) p.indiConn, err = net.Dial("tcp", p.indiServerAddr)
if err != nil { if err != nil {
log.Printf("Could not start INDI-server for INDIHUB in solo mode: %v\n", err) log.Printf("could not connect to INDI-server in solo-mode: %s\n", err)
return return err
} }
log.Println("...OK") defer p.indiConn.Close()
var connCnt uint32 // set connection to receive data
if _, err := p.indiConn.Write(getProperties); err != nil {
log.Printf("could not write to INDI-server in solo-mode: %s\n", err)
return err
}
// listen INDI-server for data
buf := make([]byte, lib.INDIServerMaxSendMsgSize, lib.INDIServerMaxSendMsgSize)
xmlFlattener := lib.NewXmlFlattener()
for { for {
if atomic.LoadInt32(&p.shouldExit) == 1 { if p.shouldExit {
break break
} }
// Wait for a connection from INDI-client n, err := p.indiConn.Read(buf)
connIn, err := p.listener.Accept()
if err != nil { if err != nil {
log.Println("could not read from INDI-server in solo-mode:", err)
break break
} }
// connection to real INDI-server // subscribe to BLOBs and catch images
connOut, err := net.Dial("tcp", p.Addr) xmlCommands := xmlFlattener.FeedChunk(buf[:n])
if err != nil {
log.Printf("%s - could not connect to INDI-server: %v\n", p.Name, err)
connIn.Close()
continue
}
connCnt += 1 for _, xmlCmd := range xmlCommands {
p.connInMap[connCnt] = connIn // catch images
p.connOutMap[connCnt] = connOut if bytes.HasPrefix(xmlCmd, setBLOBVector) {
err := p.sendImages(xmlCmd, 1, sessionID, sessionToken)
// copy requests
go func(cNum uint32) {
_, err := io.Copy(connOut, connIn)
if err == nil {
// client closed connection so closing to INDI-server
connOut.Close()
} else {
connIn.Close()
connOut.Close()
}
delete(p.connInMap, cNum)
delete(p.connOutMap, cNum)
}(connCnt)
// copy responses
go func(cNum uint32, sessID uint64, sessToken string) {
buf := make([]byte, lib.INDIServerMaxSendMsgSize, lib.INDIServerMaxSendMsgSize)
xmlFlattener := lib.NewXmlFlattener()
for {
n, err := connOut.Read(buf)
if err != nil { if err != nil {
log.Printf("%s - could not read from INDI-server: %v\n", p.Name, err) log.Println("could not send image to INDIHUB in solo-mode:", err)
connIn.Close()
return
} }
continue
}
if _, err := connIn.Write(buf[:n]); err != nil { // subscribe to BLOBs from CCDs
log.Printf("%s - could not write to INDI-client: %v\n", p.Name, err) if !bytes.HasPrefix(xmlCmd, defTextVector) {
connOut.Close() continue
return }
}
// catch images mapVal, err := mxj.NewMapXml(xmlCmd, true)
xmlCommands := xmlFlattener.FeedChunk(buf[:n]) if err != nil {
for _, xmlComm := range xmlCommands { log.Println("could not parse XML chunk in solo-mode:", err)
if !bytes.HasPrefix(xmlComm, setBLOBVector) { continue
continue }
} defTextVectorMap, _ := mapVal.ValueForKey("defTextVector")
err := p.sendImages(xmlComm, cNum, sessID, sessToken) if defTextVectorMap == nil {
if err != nil { continue
log.Printf("%s - could not send image to INDIHUB: %v\n", p.Name, err) }
defTextVectorVal := defTextVectorMap.(map[string]interface{})
if nameStr, ok := defTextVectorVal["attr_name"].(string); ok && nameStr == "DRIVER_INFO" {
if defTextVal, ok := defTextVectorVal["defText"].([]interface{}); ok {
for _, driverInfo := range defTextVal {
driverInfoVal := driverInfo.(map[string]interface{})
if driverNameStr, ok := driverInfoVal["attr_name"].(string); ok && driverNameStr == "DRIVER_EXEC" {
if execText, ok := driverInfoVal["#text"].(string); ok && p.ccdDrivers[execText] {
if deviceStr, ok := defTextVectorVal["attr_device"].(string); ok {
_, err := p.indiConn.Write([]byte(fmt.Sprintf(enableBLOB, deviceStr)))
if err != nil {
log.Printf("could not write to INDI-server in solo-mode: %s\n", err)
}
break
}
}
}
} }
} }
} }
}(connCnt, sessionID, sessionToken) }
} }
// close connections to tunnel // close connections to tunnel
if summary, err := p.Tunnel.CloseAndRecv(); err == nil { if summary, err := p.tunnel.CloseAndRecv(); err == nil {
gc := color.New(color.FgGreen) gc := color.New(color.FgGreen)
gc.Println() gc.Println()
gc.Println(" ************************************************************") gc.Println(" ************************************************************")
@ -141,20 +145,16 @@ func (p *SoloTcpProxy) Start(addr string, sessionID uint64, sessionToken string)
} else { } else {
log.Printf("Error getting solo-session summary: %v", err) log.Printf("Error getting solo-session summary: %v", err)
} }
return nil
} }
func (p *SoloTcpProxy) Close() { func (p *Agent) Close() {
atomic.SwapInt32(&p.shouldExit, 1) p.indiConn.Close()
for _, c := range p.connInMap { p.shouldExit = true
c.Close()
}
p.listener.Close()
for _, c := range p.connOutMap {
c.Close()
}
} }
func (p *SoloTcpProxy) sendImages(imagesData []byte, cNum uint32, sessID uint64, sessToken string) error { func (p *Agent) sendImages(imagesData []byte, cNum uint32, sessID uint64, sessToken string) error {
resp := &indihub.Response{ resp := &indihub.Response{
Data: imagesData, Data: imagesData,
Conn: cNum, Conn: cNum,
@ -162,5 +162,5 @@ func (p *SoloTcpProxy) sendImages(imagesData []byte, cNum uint32, sessID uint64,
SessionToken: sessToken, SessionToken: sessToken,
} }
return p.Tunnel.Send(resp) return p.tunnel.Send(resp)
} }