github.com/rootless-containers/rootlesskit/v2@v2.3.4/pkg/messages/messages.go (about)

     1  package messages
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"reflect"
     7  
     8  	"github.com/rootless-containers/rootlesskit/v2/pkg/lowlevelmsgutil"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  // Message for parent-child communication.
    13  // Sent as JSON, with uint32le length header.
    14  type Message struct {
    15  	Name string // Name is like "MessageParentHello". Automatically filled on [Send.
    16  	U
    17  }
    18  
    19  func (m *Message) FulfillName() error {
    20  	uT := reflect.TypeOf(m.U)
    21  	uV := reflect.ValueOf(m.U)
    22  	uN := uT.NumField()
    23  	for i := 0; i < uN; i++ {
    24  		uTF := uT.Field(i)
    25  		uVF := uV.Field(i)
    26  		if !uVF.IsNil() {
    27  			m.Name = uTF.Name
    28  			return nil
    29  		}
    30  	}
    31  	return fmt.Errorf("failed to fulfill the name for message %+v", m)
    32  }
    33  
    34  // U is a union.
    35  type U struct {
    36  	*ParentHello
    37  	*ChildHello
    38  	*ParentInitIdmapCompleted
    39  	*ChildInitUserNSCompleted
    40  	*ParentInitNetworkDriverCompleted
    41  	*ParentInitPortDriverCompleted
    42  }
    43  
    44  type ParentHello struct {
    45  }
    46  
    47  type ChildHello struct {
    48  }
    49  
    50  type ParentInitIdmapCompleted struct {
    51  }
    52  
    53  type ChildInitUserNSCompleted struct {
    54  }
    55  
    56  type ParentInitNetworkDriverCompleted struct {
    57  	// Fields are empty for HostNetwork.
    58  	Dev     string
    59  	IP      string
    60  	Netmask int
    61  	Gateway string
    62  	DNS     []string
    63  	MTU     int
    64  	// NetworkDriverOpaque strings are specific to driver
    65  	NetworkDriverOpaque map[string]string
    66  }
    67  
    68  type ParentInitPortDriverCompleted struct {
    69  	// Fields are empty for port driver "none"
    70  	PortDriverOpaque map[string]string
    71  }
    72  
    73  func Send(w io.Writer, m *Message) error {
    74  	if m.Name == "" {
    75  		if err := m.FulfillName(); err != nil {
    76  			return err
    77  		}
    78  	}
    79  	logrus.Debugf("Sending %+v", m)
    80  	if _, err := lowlevelmsgutil.MarshalToWriter(w, m); err != nil {
    81  		return fmt.Errorf("failed to send message %+v: %w", m, err)
    82  	}
    83  	return nil
    84  }
    85  
    86  func Recv(r io.Reader) (*Message, error) {
    87  	var m Message
    88  	if _, err := lowlevelmsgutil.UnmarshalFromReader(r, &m); err != nil {
    89  		return nil, err
    90  	}
    91  	logrus.Debugf("Received %+v", m)
    92  	if m.Name == "" {
    93  		return nil, fmt.Errorf("failed to parse message %+v", m)
    94  	}
    95  	return &m, nil
    96  }
    97  
    98  func WaitFor(r io.Reader, name string) (*Message, error) {
    99  	msg, err := Recv(r)
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  	if msg.Name != name {
   104  		return nil, fmt.Errorf("expected %q, got %+v", name, msg)
   105  	}
   106  	return msg, nil
   107  }
   108  
   109  func Name(x interface{}) string {
   110  	t := reflect.TypeOf(x)
   111  	if t.Kind() == reflect.Ptr {
   112  		return t.Elem().Name()
   113  	}
   114  	return t.Name()
   115  }