76 lines
1.7 KiB
Go
76 lines
1.7 KiB
Go
package p2p
|
|
|
|
import (
|
|
// "fmt"
|
|
"github.com/ethereum/go-ethereum/ethutil"
|
|
)
|
|
|
|
type MsgCode uint8
|
|
|
|
type Msg struct {
|
|
code MsgCode // this is the raw code as per adaptive msg code scheme
|
|
data *ethutil.Value
|
|
encoded []byte
|
|
}
|
|
|
|
func (self *Msg) Code() MsgCode {
|
|
return self.code
|
|
}
|
|
|
|
func (self *Msg) Data() *ethutil.Value {
|
|
return self.data
|
|
}
|
|
|
|
func NewMsg(code MsgCode, params ...interface{}) (msg *Msg, err error) {
|
|
|
|
// // data := [][]interface{}{}
|
|
// data := []interface{}{}
|
|
// for _, value := range params {
|
|
// if encodable, ok := value.(ethutil.RlpEncodeDecode); ok {
|
|
// data = append(data, encodable.RlpValue())
|
|
// } else if raw, ok := value.([]interface{}); ok {
|
|
// data = append(data, raw)
|
|
// } else {
|
|
// // data = append(data, interface{}(raw))
|
|
// err = fmt.Errorf("Unable to encode object of type %T", value)
|
|
// return
|
|
// }
|
|
// }
|
|
return &Msg{
|
|
code: code,
|
|
data: ethutil.NewValue(interface{}(params)),
|
|
}, nil
|
|
}
|
|
|
|
func NewMsgFromBytes(encoded []byte) (msg *Msg, err error) {
|
|
value := ethutil.NewValueFromBytes(encoded)
|
|
// Type of message
|
|
code := value.Get(0).Uint()
|
|
// Actual data
|
|
data := value.SliceFrom(1)
|
|
|
|
msg = &Msg{
|
|
code: MsgCode(code),
|
|
data: data,
|
|
// data: ethutil.NewValue(data),
|
|
encoded: encoded,
|
|
}
|
|
return
|
|
}
|
|
|
|
func (self *Msg) Decode(offset MsgCode) {
|
|
self.code = self.code - offset
|
|
}
|
|
|
|
// encode takes an offset argument to implement adaptive message coding
|
|
// the encoded message is memoized to make msgs relayed to several peers more efficient
|
|
func (self *Msg) Encode(offset MsgCode) (res []byte) {
|
|
if len(self.encoded) == 0 {
|
|
res = ethutil.NewValue(append([]interface{}{byte(self.code + offset)}, self.data.Slice()...)).Encode()
|
|
self.encoded = res
|
|
} else {
|
|
res = self.encoded
|
|
}
|
|
return
|
|
}
|