github.com/ethersphere/bee/v2@v2.2.0/pkg/pricer/headerutils/utilities.go (about)

     1  // Copyright 2021 The Swarm Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package headerutils
     6  
     7  import (
     8  	"encoding/binary"
     9  	"errors"
    10  	"github.com/ethersphere/bee/v2/pkg/p2p"
    11  	"github.com/ethersphere/bee/v2/pkg/swarm"
    12  )
    13  
    14  const (
    15  	priceFieldName  = "price"
    16  	targetFieldName = "target"
    17  	indexFieldName  = "index"
    18  )
    19  
    20  var (
    21  	// ErrFieldLength denotes p2p.Header having malformed field length in bytes
    22  	ErrFieldLength = errors.New("field length error")
    23  	// ErrNoIndexHeader denotes p2p.Header lacking specified field
    24  	ErrNoIndexHeader = errors.New("no index header")
    25  	// ErrNoTargetHeader denotes p2p.Header lacking specified field
    26  	ErrNoTargetHeader = errors.New("no target header")
    27  	// ErrNoPriceHeader denotes p2p.Header lacking specified field
    28  	ErrNoPriceHeader = errors.New("no price header")
    29  )
    30  
    31  // Headers, utility functions
    32  
    33  func MakePricingHeaders(chunkPrice uint64, addr swarm.Address) (p2p.Headers, error) {
    34  
    35  	chunkPriceInBytes := make([]byte, 8)
    36  
    37  	binary.BigEndian.PutUint64(chunkPriceInBytes, chunkPrice)
    38  
    39  	headers := p2p.Headers{
    40  		priceFieldName:  chunkPriceInBytes,
    41  		targetFieldName: addr.Bytes(),
    42  	}
    43  
    44  	return headers, nil
    45  }
    46  
    47  func MakePricingResponseHeaders(chunkPrice uint64, addr swarm.Address, index uint8) (p2p.Headers, error) {
    48  
    49  	chunkPriceInBytes := make([]byte, 8)
    50  	chunkIndexInBytes := make([]byte, 1)
    51  
    52  	binary.BigEndian.PutUint64(chunkPriceInBytes, chunkPrice)
    53  	chunkIndexInBytes[0] = index
    54  
    55  	headers := p2p.Headers{
    56  		priceFieldName:  chunkPriceInBytes,
    57  		targetFieldName: addr.Bytes(),
    58  		indexFieldName:  chunkIndexInBytes,
    59  	}
    60  
    61  	return headers, nil
    62  }
    63  
    64  // ParsePricingHeaders used by responder to read address and price from stream headers
    65  // Returns an error if no target field attached or the contents of it are not readable
    66  func ParsePricingHeaders(receivedHeaders p2p.Headers) (swarm.Address, uint64, error) {
    67  
    68  	target, err := ParseTargetHeader(receivedHeaders)
    69  	if err != nil {
    70  		return swarm.ZeroAddress, 0, err
    71  	}
    72  	price, err := ParsePriceHeader(receivedHeaders)
    73  	if err != nil {
    74  		return swarm.ZeroAddress, 0, err
    75  	}
    76  	return target, price, nil
    77  }
    78  
    79  // ParsePricingResponseHeaders used by requester to read address, price and index from response headers
    80  // Returns an error if any fields are missing or target is unreadable
    81  func ParsePricingResponseHeaders(receivedHeaders p2p.Headers) (swarm.Address, uint64, uint8, error) {
    82  	target, err := ParseTargetHeader(receivedHeaders)
    83  	if err != nil {
    84  		return swarm.ZeroAddress, 0, 0, err
    85  	}
    86  	price, err := ParsePriceHeader(receivedHeaders)
    87  	if err != nil {
    88  		return swarm.ZeroAddress, 0, 0, err
    89  	}
    90  	index, err := ParseIndexHeader(receivedHeaders)
    91  	if err != nil {
    92  		return swarm.ZeroAddress, 0, 0, err
    93  	}
    94  
    95  	return target, price, index, nil
    96  }
    97  
    98  func ParseIndexHeader(receivedHeaders p2p.Headers) (uint8, error) {
    99  	if receivedHeaders[indexFieldName] == nil {
   100  		return 0, ErrNoIndexHeader
   101  	}
   102  
   103  	if len(receivedHeaders[indexFieldName]) != 1 {
   104  		return 0, ErrFieldLength
   105  	}
   106  
   107  	index := receivedHeaders[indexFieldName][0]
   108  	return index, nil
   109  }
   110  
   111  func ParseTargetHeader(receivedHeaders p2p.Headers) (swarm.Address, error) {
   112  	if receivedHeaders[targetFieldName] == nil {
   113  		return swarm.ZeroAddress, ErrNoTargetHeader
   114  	}
   115  
   116  	target := swarm.NewAddress(receivedHeaders[targetFieldName])
   117  
   118  	return target, nil
   119  }
   120  
   121  func ParsePriceHeader(receivedHeaders p2p.Headers) (uint64, error) {
   122  	if receivedHeaders[priceFieldName] == nil {
   123  		return 0, ErrNoPriceHeader
   124  	}
   125  
   126  	if len(receivedHeaders[priceFieldName]) != 8 {
   127  		return 0, ErrFieldLength
   128  	}
   129  
   130  	receivedPrice := binary.BigEndian.Uint64(receivedHeaders[priceFieldName])
   131  	return receivedPrice, nil
   132  }