File: messages.go

package info (click to toggle)
rootlesskit 2.0.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 636 kB
  • sloc: sh: 433; makefile: 25
file content (115 lines) | stat: -rw-r--r-- 2,342 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package messages

import (
	"fmt"
	"io"
	"reflect"

	"github.com/rootless-containers/rootlesskit/v2/pkg/lowlevelmsgutil"
	"github.com/sirupsen/logrus"
)

// Message for parent-child communication.
// Sent as JSON, with uint32le length header.
type Message struct {
	Name string // Name is like "MessageParentHello". Automatically filled on [Send.
	U
}

func (m *Message) FulfillName() error {
	uT := reflect.TypeOf(m.U)
	uV := reflect.ValueOf(m.U)
	uN := uT.NumField()
	for i := 0; i < uN; i++ {
		uTF := uT.Field(i)
		uVF := uV.Field(i)
		if !uVF.IsNil() {
			m.Name = uTF.Name
			return nil
		}
	}
	return fmt.Errorf("failed to fulfill the name for message %+v", m)
}

// U is a union.
type U struct {
	*ParentHello
	*ChildHello
	*ParentInitIdmapCompleted
	*ChildInitUserNSCompleted
	*ParentInitNetworkDriverCompleted
	*ParentInitPortDriverCompleted
}

type ParentHello struct {
}

type ChildHello struct {
}

type ParentInitIdmapCompleted struct {
}

type ChildInitUserNSCompleted struct {
}

type ParentInitNetworkDriverCompleted struct {
	// Fields are empty for HostNetwork.
	Dev     string
	IP      string
	Netmask int
	Gateway string
	DNS     string
	MTU     int
	// NetworkDriverOpaque strings are specific to driver
	NetworkDriverOpaque map[string]string
}

type ParentInitPortDriverCompleted struct {
	// Fields are empty for port driver "none"
	PortDriverOpaque map[string]string
}

func Send(w io.Writer, m *Message) error {
	if m.Name == "" {
		if err := m.FulfillName(); err != nil {
			return err
		}
	}
	logrus.Debugf("Sending %+v", m)
	if _, err := lowlevelmsgutil.MarshalToWriter(w, m); err != nil {
		return fmt.Errorf("failed to send message %+v: %w", m, err)
	}
	return nil
}

func Recv(r io.Reader) (*Message, error) {
	var m Message
	if _, err := lowlevelmsgutil.UnmarshalFromReader(r, &m); err != nil {
		return nil, err
	}
	logrus.Debugf("Received %+v", m)
	if m.Name == "" {
		return nil, fmt.Errorf("failed to parse message %+v", m)
	}
	return &m, nil
}

func WaitFor(r io.Reader, name string) (*Message, error) {
	msg, err := Recv(r)
	if err != nil {
		return nil, err
	}
	if msg.Name != name {
		return nil, fmt.Errorf("expected %q, got %+v", name, msg)
	}
	return msg, nil
}

func Name(x interface{}) string {
	t := reflect.TypeOf(x)
	if t.Kind() == reflect.Ptr {
		return t.Elem().Name()
	}
	return t.Name()
}