| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | package whisper | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/p2p" | 
					
						
							| 
									
										
										
										
											2015-03-04 13:12:50 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	"gopkg.in/fatih/set.v0" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							| 
									
										
										
										
											2015-03-21 00:49:58 +01:00
										 |  |  | 	protocolVersion uint64 = 0x02 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type peer struct { | 
					
						
							|  |  |  | 	host *Whisper | 
					
						
							|  |  |  | 	peer *p2p.Peer | 
					
						
							|  |  |  | 	ws   p2p.MsgReadWriter | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// XXX Eventually this is going to reach exceptional large space. We need an expiry here | 
					
						
							|  |  |  | 	known *set.Set | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	quit chan struct{} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func NewPeer(host *Whisper, p *p2p.Peer, ws p2p.MsgReadWriter) *peer { | 
					
						
							|  |  |  | 	return &peer{host, p, ws, set.New(), make(chan struct{})} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peer) init() error { | 
					
						
							|  |  |  | 	if err := self.handleStatus(); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peer) start() { | 
					
						
							|  |  |  | 	go self.update() | 
					
						
							| 
									
										
										
										
											2015-03-10 22:43:07 +01:00
										 |  |  | 	self.peer.Debugln("whisper started") | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peer) stop() { | 
					
						
							| 
									
										
										
										
											2015-03-10 22:43:07 +01:00
										 |  |  | 	self.peer.Debugln("whisper stopped") | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	close(self.quit) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peer) update() { | 
					
						
							|  |  |  | 	relay := time.NewTicker(300 * time.Millisecond) | 
					
						
							|  |  |  | out: | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		select { | 
					
						
							|  |  |  | 		case <-relay.C: | 
					
						
							|  |  |  | 			err := self.broadcast(self.host.envelopes()) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2015-01-08 21:41:32 +01:00
										 |  |  | 				self.peer.Infoln("broadcast err:", err) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 				break out | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		case <-self.quit: | 
					
						
							|  |  |  | 			break out | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (self *peer) broadcast(envelopes []*Envelope) error { | 
					
						
							| 
									
										
										
										
											2015-03-21 00:49:58 +01:00
										 |  |  | 	envs := make([]*Envelope, 0, len(envelopes)) | 
					
						
							|  |  |  | 	for _, env := range envelopes { | 
					
						
							|  |  |  | 		if !self.known.Has(env.Hash()) { | 
					
						
							|  |  |  | 			envs = append(envs, env) | 
					
						
							|  |  |  | 			self.known.Add(env.Hash()) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-21 00:49:58 +01:00
										 |  |  | 	if len(envs) > 0 { | 
					
						
							|  |  |  | 		if err := p2p.Send(self.ws, envelopesMsg, envs); err != nil { | 
					
						
							| 
									
										
										
										
											2014-12-08 13:16:50 +01:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-21 00:49:58 +01:00
										 |  |  | 		self.peer.DebugDetailln("broadcasted", len(envs), "message(s)") | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 14:25:52 +01:00
										 |  |  | func (self *peer) addKnown(envelope *Envelope) { | 
					
						
							|  |  |  | 	self.known.Add(envelope.Hash()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | func (self *peer) handleStatus() error { | 
					
						
							|  |  |  | 	ws := self.ws | 
					
						
							| 
									
										
										
										
											2015-03-19 15:18:31 +01:00
										 |  |  | 	if err := p2p.SendItems(ws, statusMsg, protocolVersion); err != nil { | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	msg, err := ws.ReadMsg() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if msg.Code != statusMsg { | 
					
						
							|  |  |  | 		return fmt.Errorf("peer send %x before status msg", msg.Code) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-04 13:12:50 +01:00
										 |  |  | 	s := rlp.NewStream(msg.Payload) | 
					
						
							|  |  |  | 	if _, err := s.List(); err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("bad status message: %v", err) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-04 13:12:50 +01:00
										 |  |  | 	pv, err := s.Uint() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return fmt.Errorf("bad status message: %v", err) | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-04 13:12:50 +01:00
										 |  |  | 	if pv != protocolVersion { | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | 		return fmt.Errorf("protocol version mismatch %d != %d", pv, protocolVersion) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-04 13:12:50 +01:00
										 |  |  | 	return msg.Discard() // ignore anything after protocol version | 
					
						
							| 
									
										
										
										
											2014-12-08 12:43:33 +01:00
										 |  |  | } |