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  }