github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/eventchannel/event.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package eventchannel contains functionality for sending any protobuf message 16 // on a socketpair. 17 // 18 // The wire format is a uvarint length followed by a binary protobuf.Any 19 // message. 20 package eventchannel 21 22 import ( 23 "encoding/binary" 24 "fmt" 25 26 "google.golang.org/protobuf/encoding/prototext" 27 "google.golang.org/protobuf/proto" 28 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 29 pb "github.com/SagerNet/gvisor/pkg/eventchannel/eventchannel_go_proto" 30 "github.com/SagerNet/gvisor/pkg/log" 31 "github.com/SagerNet/gvisor/pkg/sync" 32 "github.com/SagerNet/gvisor/pkg/unet" 33 ) 34 35 // Emitter emits a proto message. 36 type Emitter interface { 37 // Emit writes a single eventchannel message to an emitter. Emit should 38 // return hangup = true to indicate an emitter has "hung up" and no further 39 // messages should be directed to it. 40 Emit(msg proto.Message) (hangup bool, err error) 41 42 // Close closes this emitter. Emit cannot be used after Close is called. 43 Close() error 44 } 45 46 // DefaultEmitter is the default emitter. Calls to Emit and AddEmitter are sent 47 // to this Emitter. 48 var DefaultEmitter = &multiEmitter{} 49 50 // Emit is a helper method that calls DefaultEmitter.Emit. 51 func Emit(msg proto.Message) error { 52 _, err := DefaultEmitter.Emit(msg) 53 return err 54 } 55 56 // AddEmitter is a helper method that calls DefaultEmitter.AddEmitter. 57 func AddEmitter(e Emitter) { 58 DefaultEmitter.AddEmitter(e) 59 } 60 61 // multiEmitter is an Emitter that forwards messages to multiple Emitters. 62 type multiEmitter struct { 63 // mu protects emitters. 64 mu sync.Mutex 65 // emitters is initialized lazily in AddEmitter. 66 emitters map[Emitter]struct{} 67 } 68 69 // Emit emits a message using all added emitters. 70 func (me *multiEmitter) Emit(msg proto.Message) (bool, error) { 71 me.mu.Lock() 72 defer me.mu.Unlock() 73 74 var err error 75 for e := range me.emitters { 76 hangup, eerr := e.Emit(msg) 77 if eerr != nil { 78 if err == nil { 79 err = fmt.Errorf("error emitting %v: on %v: %v", msg, e, eerr) 80 } else { 81 err = fmt.Errorf("%v; on %v: %v", err, e, eerr) 82 } 83 84 // Log as well, since most callers ignore the error. 85 log.Warningf("Error emitting %v on %v: %v", msg, e, eerr) 86 } 87 if hangup { 88 log.Infof("Hangup on eventchannel emitter %v.", e) 89 delete(me.emitters, e) 90 } 91 } 92 93 return false, err 94 } 95 96 // AddEmitter adds a new emitter. 97 func (me *multiEmitter) AddEmitter(e Emitter) { 98 me.mu.Lock() 99 defer me.mu.Unlock() 100 if me.emitters == nil { 101 me.emitters = make(map[Emitter]struct{}) 102 } 103 me.emitters[e] = struct{}{} 104 } 105 106 // Close closes all emitters. If any Close call errors, it returns the first 107 // one encountered. 108 func (me *multiEmitter) Close() error { 109 me.mu.Lock() 110 defer me.mu.Unlock() 111 var err error 112 for e := range me.emitters { 113 if eerr := e.Close(); err == nil && eerr != nil { 114 err = eerr 115 } 116 delete(me.emitters, e) 117 } 118 return err 119 } 120 121 // socketEmitter emits proto messages on a socket. 122 type socketEmitter struct { 123 socket *unet.Socket 124 } 125 126 // SocketEmitter creates a new event channel based on the given fd. 127 // 128 // SocketEmitter takes ownership of fd. 129 func SocketEmitter(fd int) (Emitter, error) { 130 s, err := unet.NewSocket(fd) 131 if err != nil { 132 return nil, err 133 } 134 135 return &socketEmitter{ 136 socket: s, 137 }, nil 138 } 139 140 // Emit implements Emitter.Emit. 141 func (s *socketEmitter) Emit(msg proto.Message) (bool, error) { 142 any, err := newAny(msg) 143 if err != nil { 144 return false, err 145 } 146 bufMsg, err := proto.Marshal(any) 147 if err != nil { 148 return false, err 149 } 150 151 // Wire format is uvarint message length followed by binary proto. 152 p := make([]byte, binary.MaxVarintLen64) 153 n := binary.PutUvarint(p, uint64(len(bufMsg))) 154 p = append(p[:n], bufMsg...) 155 for done := 0; done < len(p); { 156 n, err := s.socket.Write(p[done:]) 157 if err != nil { 158 return linuxerr.Equals(linuxerr.EPIPE, err), err 159 } 160 done += n 161 } 162 163 return false, nil 164 } 165 166 // Close implements Emitter.Emit. 167 func (s *socketEmitter) Close() error { 168 return s.socket.Close() 169 } 170 171 // debugEmitter wraps an emitter to emit stringified event messages. This is 172 // useful for debugging -- when the messages are intended for humans. 173 type debugEmitter struct { 174 inner Emitter 175 } 176 177 // DebugEmitterFrom creates a new event channel emitter by wrapping an existing 178 // raw emitter. 179 func DebugEmitterFrom(inner Emitter) Emitter { 180 return &debugEmitter{ 181 inner: inner, 182 } 183 } 184 185 func (d *debugEmitter) Emit(msg proto.Message) (bool, error) { 186 text, err := prototext.Marshal(msg) 187 if err != nil { 188 return false, err 189 } 190 ev := &pb.DebugEvent{ 191 Name: string(msg.ProtoReflect().Descriptor().FullName()), 192 Text: string(text), 193 } 194 return d.inner.Emit(ev) 195 } 196 197 func (d *debugEmitter) Close() error { 198 return d.inner.Close() 199 }