message.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. package p2p
  2. import (
  3. // "fmt"
  4. "github.com/ethereum/eth-go/ethutil"
  5. )
  6. type MsgCode uint8
  7. type Msg struct {
  8. code MsgCode // this is the raw code as per adaptive msg code scheme
  9. data *ethutil.Value
  10. encoded []byte
  11. }
  12. func (self *Msg) Code() MsgCode {
  13. return self.code
  14. }
  15. func (self *Msg) Data() *ethutil.Value {
  16. return self.data
  17. }
  18. func NewMsg(code MsgCode, params ...interface{}) (msg *Msg, err error) {
  19. // // data := [][]interface{}{}
  20. // data := []interface{}{}
  21. // for _, value := range params {
  22. // if encodable, ok := value.(ethutil.RlpEncodeDecode); ok {
  23. // data = append(data, encodable.RlpValue())
  24. // } else if raw, ok := value.([]interface{}); ok {
  25. // data = append(data, raw)
  26. // } else {
  27. // // data = append(data, interface{}(raw))
  28. // err = fmt.Errorf("Unable to encode object of type %T", value)
  29. // return
  30. // }
  31. // }
  32. return &Msg{
  33. code: code,
  34. data: ethutil.NewValue(interface{}(params)),
  35. }, nil
  36. }
  37. func NewMsgFromBytes(encoded []byte) (msg *Msg, err error) {
  38. value := ethutil.NewValueFromBytes(encoded)
  39. // Type of message
  40. code := value.Get(0).Uint()
  41. // Actual data
  42. data := value.SliceFrom(1)
  43. msg = &Msg{
  44. code: MsgCode(code),
  45. data: data,
  46. // data: ethutil.NewValue(data),
  47. encoded: encoded,
  48. }
  49. return
  50. }
  51. func (self *Msg) Decode(offset MsgCode) {
  52. self.code = self.code - offset
  53. }
  54. // encode takes an offset argument to implement adaptive message coding
  55. // the encoded message is memoized to make msgs relayed to several peers more efficient
  56. func (self *Msg) Encode(offset MsgCode) (res []byte) {
  57. if len(self.encoded) == 0 {
  58. res = ethutil.NewValue(append([]interface{}{byte(self.code + offset)}, self.data.Slice()...)).Encode()
  59. self.encoded = res
  60. } else {
  61. res = self.encoded
  62. }
  63. return
  64. }