package comms import ( "encoding/gob" "io" "log" ) type GOBChannel struct { // can be any connection, including the ssh connnection before it is // passed on to SSH during initialization of converge to agent communication Peer io.ReadWriter Encoder *gob.Encoder Decoder *gob.Decoder } func NewGOBChannel(conn io.ReadWriter) GOBChannel { return GOBChannel{ Peer: conn, Encoder: gob.NewEncoder(conn), Decoder: gob.NewDecoder(conn), } } // Asynchronous send and receive on a single connection is guaranteed to preserver ordering of // messages. We use asynchronous to void blocking indefinitely or depending on network timeouts. func (channel GOBChannel) SendAsync(obj any, done chan<- any, errors chan<- error) { go func() { err := channel.Send(obj) if err != nil { errors <- err } else { done <- true } }() } func (channel GOBChannel) ReceiveAsync(result chan<- any, errors chan<- error) { go func() { value, err := channel.Receive() if err != nil { errors <- err } else { result <- value } }() } func (channel GOBChannel) Send(object any) error { err := channel.Encoder.Encode(ConvergeMessage{Value: object}) if err != nil { log.Printf("Encoding error %v", err) } return err } func (channel GOBChannel) Receive() (any, error) { var target ConvergeMessage err := channel.Decoder.Decode(&target) return target.Value, err }