converge/pkg/comms/gobchannel.go
Erik Brakkee ada34495ef GOB channel for easily and asynchronously using GOB on a single network connection, also dealing with timeouts and errors in a good way.
Protocol version is now checked when the agent connects to the converge server.

Next up: sending connection metadata and username password from server to agent and sending environment information back to the server. This means then that the side channel will only be used for expiry time messages and session type with the client id passed in so the converge server can than correlate the results back to the correct channel.
2024-09-08 11:16:49 +02:00

63 lines
1.4 KiB
Go

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
}