github.com/amazechain/amc@v0.1.3/internal/p2p/sender.go (about) 1 package p2p 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/kr/pretty" 8 "github.com/libp2p/go-libp2p/core/network" 9 "github.com/libp2p/go-libp2p/core/peer" 10 "github.com/libp2p/go-libp2p/core/protocol" 11 "github.com/pkg/errors" 12 ssz "github.com/prysmaticlabs/fastssz" 13 "go.opencensus.io/trace" 14 ) 15 16 // Send a message to a specific peer. The returned stream may be used for reading, but has been 17 // closed for writing. 18 // 19 // When done, the caller must Close or Reset on the stream. 20 func (s *Service) Send(ctx context.Context, message interface{}, baseTopic string, pid peer.ID) (network.Stream, error) { 21 ctx, span := trace.StartSpan(ctx, "p2p.Send") 22 defer span.End() 23 if err := VerifyTopicMapping(baseTopic, message); err != nil { 24 return nil, err 25 } 26 topic := baseTopic + s.Encoding().ProtocolSuffix() 27 span.AddAttributes(trace.StringAttribute("topic", topic)) 28 29 log.Trace(fmt.Sprintf("Sending RPC request to peer %s", pid.String()), "topic", topic, "request", pretty.Sprint(message)) 30 31 // Apply max dial timeout when opening a new stream. 32 ctx, cancel := context.WithTimeout(ctx, maxDialTimeout) 33 defer cancel() 34 35 stream, err := s.host.NewStream(ctx, pid, protocol.ID(topic)) 36 if err != nil { 37 //tracing.AnnotateError(span, err) 38 return nil, err 39 } 40 castedMsg, ok := message.(ssz.Marshaler) 41 if !ok { 42 return nil, errors.Errorf("%T does not support the ssz marshaller interface", message) 43 } 44 if _, err := s.Encoding().EncodeWithMaxLength(stream, castedMsg); err != nil { 45 //tracing.AnnotateError(span, err) 46 _err := stream.Reset() 47 _ = _err 48 return nil, err 49 } 50 51 // Close stream for writing. 52 if err := stream.CloseWrite(); err != nil { 53 //tracing.AnnotateError(span, err) 54 _err := stream.Reset() 55 _ = _err 56 return nil, err 57 } 58 59 return stream, nil 60 }