github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/fleetspeak/src/server/comms/comms.go (about)

     1  // Copyright 2017 Google Inc.
     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  //     https://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 comms defines the interface used by the Fleetspeak modules which
    16  // communicate with clients.
    17  package comms
    18  
    19  import (
    20  	"crypto"
    21  	"errors"
    22  	"net"
    23  	"sync"
    24  	"time"
    25  
    26  	"context"
    27  
    28  	log "github.com/golang/glog"
    29  	"github.com/google/fleetspeak/fleetspeak/src/common"
    30  	"github.com/google/fleetspeak/fleetspeak/src/server/authorizer"
    31  	"github.com/google/fleetspeak/fleetspeak/src/server/db"
    32  	"github.com/google/fleetspeak/fleetspeak/src/server/stats"
    33  
    34  	fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak"
    35  )
    36  
    37  // A Communicator can communicate with clients through some means (HTTP, etc).
    38  type Communicator interface {
    39  	Setup(Context) error // Configure the communicator to work with a Server.
    40  	Start() error        // Tells the communicator to start sending and receiving messages.
    41  	Stop()               // Tells the communicator to stop sending and receiving messages.
    42  }
    43  
    44  // A ClientInfo is the basic information that we have about a client.
    45  type ClientInfo struct {
    46  	ID          common.ClientID
    47  	Key         crypto.PublicKey
    48  	Labels      []*fspb.Label
    49  	Blacklisted bool
    50  	Cached      bool // Whether the data was retrieved from a cache.
    51  }
    52  
    53  // A ConnectionInfo is the information that the FS system gathers and maintains
    54  // about a particular connection to a client.
    55  type ConnectionInfo struct {
    56  	Addr                     net.Addr
    57  	Client                   ClientInfo
    58  	ContactID                db.ContactID
    59  	NonceSent, NonceReceived uint64
    60  	AuthClientInfo           authorizer.ClientInfo
    61  
    62  	// Number of outstanding message tokens we have for the client.
    63  	messageTokens     map[string]uint64
    64  	messageTokensLock sync.RWMutex
    65  
    66  	// These are only set for streaming connections.
    67  	Notices <-chan struct{} // publishes when there may be a new message for the client
    68  	Fin     func()          // should be called to indicate that the streaming connection is closed.
    69  }
    70  
    71  // MessageTokens returns a copy of the current token available count. Thread safe.
    72  func (i *ConnectionInfo) MessageTokens() map[string]uint64 {
    73  	i.messageTokensLock.RLock()
    74  	defer i.messageTokensLock.RUnlock()
    75  
    76  	if i.messageTokens == nil {
    77  		return nil
    78  	}
    79  
    80  	ret := make(map[string]uint64)
    81  	for k, v := range i.messageTokens {
    82  		ret[k] = v
    83  	}
    84  	return ret
    85  }
    86  
    87  // AddMessageTokens changes the tokens available count according
    88  // to the provided delta.
    89  func (i *ConnectionInfo) AddMessageTokens(delta map[string]uint64) {
    90  	i.messageTokensLock.Lock()
    91  	defer i.messageTokensLock.Unlock()
    92  
    93  	if i.messageTokens == nil {
    94  		i.messageTokens = make(map[string]uint64)
    95  	}
    96  
    97  	for k, v := range delta {
    98  		i.messageTokens[k] += v
    99  	}
   100  }
   101  
   102  // SubtractMessageTokens changes the tokens available count according
   103  // to the provided delta.
   104  func (i *ConnectionInfo) SubtractMessageTokens(delta map[string]uint64) {
   105  	i.messageTokensLock.Lock()
   106  	defer i.messageTokensLock.Unlock()
   107  
   108  	for k, v := range delta {
   109  		if v > i.messageTokens[k] {
   110  			log.Exitf("Attempt to consume %d tokens but only have %d.", v, i.messageTokens[k])
   111  		}
   112  		i.messageTokens[k] -= v
   113  	}
   114  }
   115  
   116  // ErrNotAuthorized is returned by certain methods to indicate that the client
   117  // is not authorized to communicate with this server.
   118  var ErrNotAuthorized = errors.New("not authorized")
   119  
   120  // A Context defines the view of the Fleetspeak server provided to a Communicator.
   121  type Context interface {
   122  
   123  	// InitializeConnection attempts to validate and configure a client
   124  	// connection, and performs an initial exchange of messages.
   125  	//
   126  	// On success this effectively calls both HandleMessagesFromClient and
   127  	// GetMessagesForClient.
   128  	//
   129  	// The returned ContactData should be sent back to the client unconditionally,
   130  	// in order to update the client's de-duplication nonce.
   131  	//
   132  	// In addition, returns an indication whether there might be additional
   133  	// messages for the client.
   134  	InitializeConnection(ctx context.Context, addr net.Addr, key crypto.PublicKey, wcd *fspb.WrappedContactData, streaming bool) (i *ConnectionInfo, d *fspb.ContactData, more bool, err error)
   135  
   136  	// ValidateMessagesFromClient validates the message contained in WrappedContactData.
   137  	// On successful validation it returns the fspb.ValidationInfo data structure.
   138  	ValidateMessagesFromClient(ctx context.Context, info *ConnectionInfo, wcd *fspb.WrappedContactData) (*fspb.ValidationInfo, error)
   139  
   140  	// HandleMessagesFromClient processes the messages contained in a WrappedContactData
   141  	// received from the client.  The ConnectionInfo parameter should have been
   142  	// created by an InitializeConnection call made for this connection.
   143  	HandleMessagesFromClient(ctx context.Context, info *ConnectionInfo, wcd *fspb.WrappedContactData) error
   144  
   145  	// GetMessagesForClient finds unprocessed messages for a given client and
   146  	// reserves them for processing. The ConnectionInfo parameter should have been
   147  	// created by an InitializeConnection call made for this connection.
   148  	//
   149  	// In addition to some messages, also indicates wether there may be more
   150  	// messages to get.
   151  	//
   152  	// Returns nil, false, nil when there are no outstanding messages for
   153  	// the client.
   154  	GetMessagesForClient(ctx context.Context, info *ConnectionInfo) (data *fspb.ContactData, more bool, err error)
   155  
   156  	// ReadFile returns the data and modification time of file. Caller is
   157  	// responsible for closing data.
   158  	//
   159  	// Calls to data are permitted to fail if ctx is canceled or expired.
   160  	ReadFile(ctx context.Context, service, name string) (data db.ReadSeekerCloser, modtime time.Time, err error)
   161  
   162  	// IsNotFound returns whether an error returned by ReadFile indicates that the
   163  	// file was not found.
   164  	IsNotFound(err error) bool
   165  
   166  	// StatsCollector returns the stats.Collector used by the Fleetspeak
   167  	// system.
   168  	StatsCollector() stats.Collector
   169  
   170  	// Authorizer returns the authorizer.Authorizer used by the Fleetspeak
   171  	// system.  The Communicator is responsible for calling Accept1.
   172  	Authorizer() authorizer.Authorizer
   173  }