github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/p2pserver/common/common.go (about)

     1  package common
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"time"
     8  
     9  	"github.com/sixexorg/magnetic-ring/common"
    10  	"github.com/sixexorg/magnetic-ring/rlp"
    11  )
    12  
    13  type Msg struct {
    14  	Code       uint64
    15  	Type       string
    16  	Size       uint32 // size of the paylod
    17  	Payload    io.Reader
    18  	ReceivedAt time.Time
    19  }
    20  
    21  // for test ......
    22  func EncAndDec(msgcode uint64, data interface{}) error {
    23  	size, r, err := rlp.EncodeToReader(data)
    24  	if err != nil {
    25  		return err
    26  	}
    27  	rawmsg := Msg{Code: msgcode, Size: uint32(size), Payload: r}
    28  
    29  	codestr := TransCodeUToStr(rawmsg.Code)
    30  	fmt.Println(" ******** codestr:", codestr)
    31  	val, err := MakeEmptyMessage(codestr)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	s := rlp.NewStream(rawmsg.Payload, uint64(rawmsg.Size))
    37  	if err := s.Decode(val); err != nil {
    38  		return newPeerError(errInvalidMsg, "(code %x) (size %d) %v", rawmsg.Code, rawmsg.Size, err)
    39  		// return errors.New("(code %x) (size %d) %v")
    40  	}
    41  	return nil
    42  }
    43  
    44  //
    45  func Send(w MsgWriter, msgcode uint64, data interface{}) error {
    46  	size, r, err := rlp.EncodeToReader(data)
    47  	if err != nil {
    48  		return err
    49  	}
    50  	return w.WriteMsg(Msg{Code: msgcode, Size: uint32(size), Payload: r})
    51  }
    52  
    53  // Decode parses the RLP content of a message into
    54  // the given value, which must be a pointer.
    55  //
    56  // For the decoding rules, please see package rlp.
    57  func (msg Msg) Decode(val interface{}) error {
    58  	s := rlp.NewStream(msg.Payload, uint64(msg.Size))
    59  	if err := s.Decode(val); err != nil {
    60  		return newPeerError(errInvalidMsg, "(code %d) (size %d) %v", msg.Code, msg.Size, err)
    61  		// return errors.New("(code %x) (size %d) %v")
    62  	}
    63  	return nil
    64  }
    65  
    66  func (msg Msg) String() string {
    67  	return fmt.Sprintf("msg #%v (%v bytes)", msg.Code, msg.Size)
    68  }
    69  
    70  // Discard reads any remaining payload data into a black hole.
    71  func (msg Msg) Discard() error {
    72  	_, err := io.Copy(ioutil.Discard, msg.Payload)
    73  	return err
    74  }
    75  func (msg *Msg) DistinctSk() (common.Hash, error) {
    76  	buff, err := rlp.EncodeToBytes(msg)
    77  	if err != nil {
    78  		return common.Hash{}, err
    79  	}
    80  	return common.ParseHashFromBytes(common.Sha256(buff))
    81  }
    82  
    83  type MsgReader interface {
    84  	ReadMsg() (Msg, error)
    85  }
    86  
    87  type MsgWriter interface {
    88  	// WriteMsg sends a message. It will block until the message's
    89  	// Payload has been consumed by the other end.
    90  	//
    91  	// Note that messages can be sent only once because their
    92  	// payload reader is drained.
    93  	WriteMsg(Msg) error
    94  }
    95  
    96  // MsgReadWriter provides reading and writing of encoded messages.
    97  // Implementations should ensure that ReadMsg and WriteMsg can be
    98  // called simultaneously from multiple goroutines.
    99  type MsgReadWriter interface {
   100  	MsgReader
   101  	MsgWriter
   102  	Close(err ...error)
   103  }