76 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			76 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package p2p
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									// "fmt"
							 | 
						||
| 
								 | 
							
									"github.com/ethereum/eth-go/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
							 | 
						||
| 
								 | 
							
								}
							 |