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 }