github.com/ethersphere/bee/v2@v2.2.0/pkg/p2p/protobuf/protobuf.go (about) 1 // Copyright 2020 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 protobuf 6 7 import ( 8 "context" 9 "errors" 10 "io" 11 12 "github.com/ethersphere/bee/v2/pkg/p2p" 13 ggio "github.com/gogo/protobuf/io" 14 "github.com/gogo/protobuf/proto" 15 ) 16 17 const delimitedReaderMaxSize = 128 * 1024 // max message size 18 19 var ErrTimeout = errors.New("timeout") 20 21 type Message = proto.Message 22 23 func NewWriterAndReader(s p2p.Stream) (Writer, Reader) { 24 return NewWriter(s), NewReader(s) 25 } 26 27 func NewReader(r io.Reader) Reader { 28 return newReader(ggio.NewDelimitedReader(r, delimitedReaderMaxSize)) 29 } 30 31 func NewWriter(w io.Writer) Writer { 32 return newWriter(ggio.NewDelimitedWriter(w)) 33 } 34 35 func ReadMessages(r io.Reader, newMessage func() Message) (m []Message, err error) { 36 pr := NewReader(r) 37 for { 38 msg := newMessage() 39 if err := pr.ReadMsg(msg); err != nil { 40 if errors.Is(err, io.EOF) { 41 break 42 } 43 return nil, err 44 } 45 m = append(m, msg) 46 } 47 return m, nil 48 } 49 50 type Reader struct { 51 ggio.Reader 52 } 53 54 func newReader(r ggio.Reader) Reader { 55 return Reader{Reader: r} 56 } 57 58 func (r Reader) ReadMsgWithContext(ctx context.Context, msg proto.Message) error { 59 errChan := make(chan error, 1) 60 go func() { 61 errChan <- r.ReadMsg(msg) 62 }() 63 64 select { 65 case err := <-errChan: 66 return err 67 case <-ctx.Done(): 68 return ctx.Err() 69 } 70 } 71 72 type Writer struct { 73 ggio.Writer 74 } 75 76 func newWriter(r ggio.Writer) Writer { 77 return Writer{Writer: r} 78 } 79 80 func (w Writer) WriteMsgWithContext(ctx context.Context, msg proto.Message) error { 81 errChan := make(chan error, 1) 82 go func() { 83 errChan <- w.WriteMsg(msg) 84 }() 85 86 select { 87 case err := <-errChan: 88 return err 89 case <-ctx.Done(): 90 return ctx.Err() 91 } 92 }