github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/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  	"github.com/ttpreport/gvisor-ligolo/pkg/errors/linuxerr"
    27  	pb "github.com/ttpreport/gvisor-ligolo/pkg/eventchannel/eventchannel_go_proto"
    28  	"github.com/ttpreport/gvisor-ligolo/pkg/log"
    29  	"github.com/ttpreport/gvisor-ligolo/pkg/sync"
    30  	"github.com/ttpreport/gvisor-ligolo/pkg/unet"
    31  	"google.golang.org/protobuf/encoding/prototext"
    32  	"google.golang.org/protobuf/proto"
    33  	"google.golang.org/protobuf/types/known/anypb"
    34  )
    35  
    36  // Emitter emits a proto message.
    37  type Emitter interface {
    38  	// Emit writes a single eventchannel message to an emitter. Emit should
    39  	// return hangup = true to indicate an emitter has "hung up" and no further
    40  	// messages should be directed to it.
    41  	Emit(msg proto.Message) (hangup bool, err error)
    42  
    43  	// Close closes this emitter. Emit cannot be used after Close is called.
    44  	Close() error
    45  }
    46  
    47  // DefaultEmitter is the default emitter. Calls to Emit and AddEmitter are sent
    48  // to this Emitter.
    49  var DefaultEmitter = &multiEmitter{}
    50  
    51  // Emit is a helper method that calls DefaultEmitter.Emit.
    52  func Emit(msg proto.Message) error {
    53  	_, err := DefaultEmitter.Emit(msg)
    54  	return err
    55  }
    56  
    57  // LogEmit is a helper method that calls DefaultEmitter.Emit.
    58  // It also logs a warning message when an error occurs.
    59  func LogEmit(msg proto.Message) error {
    60  	_, err := DefaultEmitter.Emit(msg)
    61  	if err != nil {
    62  		log.Warningf("unable to emit event: %s", err)
    63  	}
    64  	return err
    65  }
    66  
    67  // AddEmitter is a helper method that calls DefaultEmitter.AddEmitter.
    68  func AddEmitter(e Emitter) {
    69  	DefaultEmitter.AddEmitter(e)
    70  }
    71  
    72  // HaveEmitters indicates if any emitters have been registered to the
    73  // default emitter.
    74  func HaveEmitters() bool {
    75  	DefaultEmitter.mu.Lock()
    76  	defer DefaultEmitter.mu.Unlock()
    77  
    78  	return len(DefaultEmitter.emitters) > 0
    79  }
    80  
    81  // multiEmitter is an Emitter that forwards messages to multiple Emitters.
    82  type multiEmitter struct {
    83  	// mu protects emitters.
    84  	mu sync.Mutex
    85  	// emitters is initialized lazily in AddEmitter.
    86  	emitters map[Emitter]struct{}
    87  }
    88  
    89  // Emit emits a message using all added emitters.
    90  func (me *multiEmitter) Emit(msg proto.Message) (bool, error) {
    91  	me.mu.Lock()
    92  	defer me.mu.Unlock()
    93  
    94  	var err error
    95  	for e := range me.emitters {
    96  		hangup, eerr := e.Emit(msg)
    97  		if eerr != nil {
    98  			if err == nil {
    99  				err = fmt.Errorf("error emitting %v: on %v: %v", msg, e, eerr)
   100  			} else {
   101  				err = fmt.Errorf("%v; on %v: %v", err, e, eerr)
   102  			}
   103  
   104  			// Log as well, since most callers ignore the error.
   105  			log.Warningf("Error emitting %v on %v: %v", msg, e, eerr)
   106  		}
   107  		if hangup {
   108  			log.Infof("Hangup on eventchannel emitter %v.", e)
   109  			delete(me.emitters, e)
   110  		}
   111  	}
   112  
   113  	return false, err
   114  }
   115  
   116  // AddEmitter adds a new emitter.
   117  func (me *multiEmitter) AddEmitter(e Emitter) {
   118  	me.mu.Lock()
   119  	defer me.mu.Unlock()
   120  	if me.emitters == nil {
   121  		me.emitters = make(map[Emitter]struct{})
   122  	}
   123  	me.emitters[e] = struct{}{}
   124  }
   125  
   126  // Close closes all emitters. If any Close call errors, it returns the first
   127  // one encountered.
   128  func (me *multiEmitter) Close() error {
   129  	me.mu.Lock()
   130  	defer me.mu.Unlock()
   131  	var err error
   132  	for e := range me.emitters {
   133  		if eerr := e.Close(); err == nil && eerr != nil {
   134  			err = eerr
   135  		}
   136  		delete(me.emitters, e)
   137  	}
   138  	return err
   139  }
   140  
   141  // socketEmitter emits proto messages on a socket.
   142  type socketEmitter struct {
   143  	socket *unet.Socket
   144  }
   145  
   146  // SocketEmitter creates a new event channel based on the given fd.
   147  //
   148  // SocketEmitter takes ownership of fd.
   149  func SocketEmitter(fd int) (Emitter, error) {
   150  	s, err := unet.NewSocket(fd)
   151  	if err != nil {
   152  		return nil, err
   153  	}
   154  
   155  	return &socketEmitter{
   156  		socket: s,
   157  	}, nil
   158  }
   159  
   160  // Emit implements Emitter.Emit.
   161  func (s *socketEmitter) Emit(msg proto.Message) (bool, error) {
   162  	any, err := anypb.New(msg)
   163  	if err != nil {
   164  		return false, err
   165  	}
   166  	bufMsg, err := proto.Marshal(any)
   167  	if err != nil {
   168  		return false, err
   169  	}
   170  
   171  	// Wire format is uvarint message length followed by binary proto.
   172  	p := make([]byte, binary.MaxVarintLen64)
   173  	n := binary.PutUvarint(p, uint64(len(bufMsg)))
   174  	p = append(p[:n], bufMsg...)
   175  	for done := 0; done < len(p); {
   176  		n, err := s.socket.Write(p[done:])
   177  		if err != nil {
   178  			return linuxerr.Equals(linuxerr.EPIPE, err), err
   179  		}
   180  		done += n
   181  	}
   182  
   183  	return false, nil
   184  }
   185  
   186  // Close implements Emitter.Emit.
   187  func (s *socketEmitter) Close() error {
   188  	return s.socket.Close()
   189  }
   190  
   191  // debugEmitter wraps an emitter to emit stringified event messages. This is
   192  // useful for debugging -- when the messages are intended for humans.
   193  type debugEmitter struct {
   194  	inner Emitter
   195  }
   196  
   197  // DebugEmitterFrom creates a new event channel emitter by wrapping an existing
   198  // raw emitter.
   199  func DebugEmitterFrom(inner Emitter) Emitter {
   200  	return &debugEmitter{
   201  		inner: inner,
   202  	}
   203  }
   204  
   205  func (d *debugEmitter) Emit(msg proto.Message) (bool, error) {
   206  	text, err := prototext.Marshal(msg)
   207  	if err != nil {
   208  		return false, err
   209  	}
   210  	ev := &pb.DebugEvent{
   211  		Name: string(msg.ProtoReflect().Descriptor().FullName()),
   212  		Text: string(text),
   213  	}
   214  	return d.inner.Emit(ev)
   215  }
   216  
   217  func (d *debugEmitter) Close() error {
   218  	return d.inner.Close()
   219  }