diff options
| -rw-r--r-- | xA/xA.go | 52 | 
1 files changed, 27 insertions, 25 deletions
| @@ -15,6 +15,7 @@ import (  	"net"  	"os"  	"slices" +	"sync"  	"time"  	"fyne.io/fyne/v2" @@ -167,6 +168,9 @@ var (  	backendAddress string  	backendContext context.Context  	backendCancel  context.CancelFunc +	backendConn    net.Conn + +	backendLock sync.Mutex  	// Connection state: @@ -231,20 +235,27 @@ func relayReadMessage(r io.Reader) (m RelayEventMessage, ok bool) {  	return m, true  } -func relayWriteMessage(conn net.Conn, data RelayCommandData) bool { +func relaySend(data RelayCommandData, callback callback) bool { +	backendLock.Lock() +	defer backendLock.Unlock() +  	m := RelayCommandMessage{  		CommandSeq: commandSeq,  		Data:       data,  	} +	if callback != nil { +		commandCallbacks[m.CommandSeq] = callback +	}  	commandSeq++ +	// TODO(p): Handle errors better.  	b, ok := m.AppendTo(make([]byte, 4))  	if !ok {  		log.Println("Command serialization failed")  		return false  	}  	binary.BigEndian.PutUint32(b[:4], uint32(len(b)-4)) -	if _, err := conn.Write(b); err != nil { +	if _, err := backendConn.Write(b); err != nil {  		log.Println("Command send failed: " + err.Error())  		return false  	} @@ -255,15 +266,6 @@ func relayWriteMessage(conn net.Conn, data RelayCommandData) bool {  	return true  } -func relaySend(data RelayCommandData, callback callback) { -	if callback != nil { -		commandCallbacks[commandSeq] = callback -	} - -	// TODO(p): Get the net.Conn from somewhere. -	//relayWriteMessage(nil, data) -} -  // --- Buffers -----------------------------------------------------------------  func bufferByName(name string) *buffer { @@ -619,7 +621,9 @@ func relayProcessBufferLine(b *buffer, m *RelayEventDataBufferLine) {  func relayProcessCallbacks(  	commandSeq uint32, err string, response *RelayResponseData) {  	if handler, ok := commandCallbacks[commandSeq]; !ok { -		// TODO(p): Warn about an unawaited response. +		if *debug { +			log.Printf("unawaited response: %+v\n", *response) +		}  	} else {  		delete(commandCallbacks, commandSeq)  		if handler != nil { @@ -833,27 +837,25 @@ func relayRun() {  	backendContext, backendCancel = context.WithCancel(context.Background())  	defer backendCancel() -	conn, err := net.Dial("tcp", backendAddress) +	var err error +	backendLock.Lock() +	backendConn, err = net.Dial("tcp", backendAddress) +	backendLock.Unlock()  	if err != nil {  		log.Println("Connection failed: " + err.Error())  		// TODO(p): Display errors to the user.  		return  	} -	defer conn.Close() +	defer backendConn.Close() -	// TODO(p): How to send messages? -	//  - It would probably make the most sense to have either a chan -	//    (which makes code synchronize), or a locked slice. -	//  - But I also need to wake the sender up somehow, -	//    so maybe use a channel after all. -	//     - Or maybe use a channel just for the signalling. -	//  - Sending (semi-)synchronously is also an option, perhaps. -	// TODO(p): Handle any errors here. -	_ = relayWriteMessage(conn, RelayCommandData{ +	// TODO(p): Figure out locking. +	//  - Messages are currently sent (semi-)synchronously, directly. +	//  - Is the net.Conn actually async-safe? +	relaySend(RelayCommandData{  		Variant: &RelayCommandDataHello{Version: RelayVersion}, -	}) +	}, nil) -	relayMessages := relayMakeReceiver(backendContext, conn) +	relayMessages := relayMakeReceiver(backendContext, backendConn)  	for {  		select {  		case m, ok := <-relayMessages: | 
