github.com/google/fleetspeak@v0.1.15-0.20240426164851-4f31f62c1aea/fleetspeak/src/client/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 client 16 17 import ( 18 "context" 19 "crypto/x509" 20 "encoding/hex" 21 "fmt" 22 23 log "github.com/golang/glog" 24 "google.golang.org/protobuf/proto" 25 tspb "google.golang.org/protobuf/types/known/timestamppb" 26 27 "github.com/google/fleetspeak/fleetspeak/src/client/comms" 28 "github.com/google/fleetspeak/fleetspeak/src/client/service" 29 "github.com/google/fleetspeak/fleetspeak/src/client/stats" 30 "github.com/google/fleetspeak/fleetspeak/src/common" 31 32 clpb "github.com/google/fleetspeak/fleetspeak/src/client/proto/fleetspeak_client" 33 fspb "github.com/google/fleetspeak/fleetspeak/src/common/proto/fleetspeak" 34 ) 35 36 // commsContext is the default implementation for comms.Context. 37 type commsContext struct { 38 c *Client 39 } 40 41 // Outbox implements comms.Context. 42 func (c commsContext) Outbox() <-chan comms.MessageInfo { 43 return c.c.outbox 44 } 45 46 // ProcessingBeacon implements comms.Context. 47 func (c commsContext) ProcessingBeacon() <-chan struct{} { 48 return c.c.processingBeacon 49 } 50 51 // MakeContactData implements comms.Context. 52 func (c commsContext) MakeContactData(toSend []*fspb.Message, baseCount map[string]uint64) (wcd *fspb.WrappedContactData, processedMessages map[string]uint64, err error) { 53 defer func() { 54 c.c.stats.ContactDataCreated(wcd, err) 55 }() 56 57 am, pm := c.c.sc.Counts() 58 allowedMessages := make(map[string]uint64) 59 for k, a := range am { 60 if b, ok := baseCount[k]; !ok { 61 allowedMessages[k] = inboxSize - (a - pm[k]) 62 } else { 63 allowedMessages[k] = pm[k] - b 64 } 65 } 66 log.V(2).Infof("Creating ContactData with %d messages and giving tokens: %v", len(toSend), allowedMessages) 67 68 // Create the bytes transferred with this contact. 69 cd := &fspb.ContactData{ 70 SequencingNonce: c.c.config.SequencingNonce(), 71 Messages: toSend, 72 ClientClock: tspb.Now(), 73 AllowedMessages: allowedMessages, 74 } 75 b, err := proto.Marshal(cd) 76 if err != nil { 77 return nil, nil, err 78 } 79 80 // Pick the non-repetitive part out of the config manager's labels. 81 labels := c.c.config.Labels() 82 stringLabels := make([]string, 0, len(labels)) 83 for _, l := range labels { 84 stringLabels = append(stringLabels, l.Label) 85 } 86 // Create extra sigs. 87 sigs := make([]*fspb.Signature, 0, len(c.c.signers)) 88 for _, signer := range c.c.signers { 89 if sig := signer.SignContact(b); sig != nil { 90 sigs = append(sigs, sig) 91 } 92 } 93 94 return &fspb.WrappedContactData{ 95 ContactData: b, 96 Signatures: sigs, 97 ClientLabels: stringLabels, 98 }, pm, nil 99 } 100 101 // ProcessContactData implements comms.Context. 102 func (c commsContext) ProcessContactData(ctx context.Context, cd *fspb.ContactData, streaming bool) (err error) { 103 defer func() { 104 c.c.stats.ContactDataProcessed(cd, streaming, err) 105 }() 106 107 if !streaming { 108 c.c.config.SetSequencingNonce(cd.SequencingNonce) 109 } 110 for _, m := range cd.Messages { 111 if err := c.c.ProcessMessage(ctx, service.AckMessage{M: m}); err != nil { 112 log.Warningf("Unable to process message[%v] from server: %v", hex.EncodeToString(m.MessageId), err) 113 } 114 } 115 return nil 116 } 117 118 // ChainRevoked implements comms.Context. 119 func (c commsContext) ChainRevoked(chain []*x509.Certificate) bool { 120 return c.c.config.ChainRevoked(chain) 121 } 122 123 // CurrentID implements comms.Context. 124 func (c commsContext) CurrentID() common.ClientID { 125 return c.c.config.ClientID() 126 } 127 128 // CurrentIdentity implements comms.Context. 129 func (c commsContext) CurrentIdentity() (comms.ClientIdentity, error) { 130 p := c.c.config.CurrentState() 131 if len(p.ClientKey) == 0 { 132 return comms.ClientIdentity{}, fmt.Errorf("ClientKey not set") 133 } 134 135 k, err := x509.ParseECPrivateKey(p.ClientKey) 136 if err != nil { 137 return comms.ClientIdentity{}, fmt.Errorf("failed to parse ClientKey: %v", err) 138 } 139 id, err := common.MakeClientID(k.Public()) 140 if err != nil { 141 return comms.ClientIdentity{}, fmt.Errorf("failed to create ClientID: %v", err) 142 } 143 144 return comms.ClientIdentity{ 145 ID: id, 146 Private: k, 147 Public: k.Public(), 148 }, nil 149 } 150 151 // CommunicatorConfig implements comms.Context. 152 func (c commsContext) ServerInfo() (comms.ServerInfo, error) { 153 cfg := c.c.config.Configuration() 154 155 return comms.ServerInfo{ 156 TrustedCerts: cfg.TrustedCerts, 157 Servers: cfg.Servers, 158 Proxy: cfg.Proxy, 159 ClientCertificateHeader: cfg.ClientCertificateHeader, 160 ServerName: cfg.ServerName, 161 }, nil 162 } 163 164 // CommunicatorConfig implements comms.Context. 165 func (c commsContext) CommunicatorConfig() *clpb.CommunicatorConfig { 166 return c.c.config.CommunicatorConfig() 167 } 168 169 // Stats implements comms.Context. 170 func (c commsContext) Stats() stats.Collector { 171 return c.c.stats 172 }