github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/swarm/pss/ping.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // +build !nopssprotocol,!nopssping
    18  
    19  package pss
    20  
    21  import (
    22  	"context"
    23  	"errors"
    24  	"time"
    25  
    26  	"github.com/ethereum/go-ethereum/p2p"
    27  	"github.com/ethereum/go-ethereum/p2p/protocols"
    28  	"github.com/ethereum/go-ethereum/swarm/log"
    29  )
    30  
    31  // Generic ping protocol implementation for
    32  // pss devp2p protocol emulation
    33  type PingMsg struct {
    34  	Created time.Time
    35  	Pong    bool // set if message is pong reply
    36  }
    37  
    38  type Ping struct {
    39  	Pong bool      // toggle pong reply upon ping receive
    40  	OutC chan bool // trigger ping
    41  	InC  chan bool // optional, report back to calling code
    42  }
    43  
    44  func (p *Ping) pingHandler(ctx context.Context, msg interface{}) error {
    45  	var pingmsg *PingMsg
    46  	var ok bool
    47  	if pingmsg, ok = msg.(*PingMsg); !ok {
    48  		return errors.New("invalid msg")
    49  	}
    50  	log.Debug("ping handler", "msg", pingmsg, "outc", p.OutC)
    51  	if p.InC != nil {
    52  		p.InC <- pingmsg.Pong
    53  	}
    54  	if p.Pong && !pingmsg.Pong {
    55  		p.OutC <- true
    56  	}
    57  	return nil
    58  }
    59  
    60  var PingProtocol = &protocols.Spec{
    61  	Name:       "psstest",
    62  	Version:    1,
    63  	MaxMsgSize: 1024,
    64  	Messages: []interface{}{
    65  		PingMsg{},
    66  	},
    67  }
    68  
    69  var PingTopic = ProtocolTopic(PingProtocol)
    70  
    71  func NewPingProtocol(ping *Ping) *p2p.Protocol {
    72  	return &p2p.Protocol{
    73  		Name:    PingProtocol.Name,
    74  		Version: PingProtocol.Version,
    75  		Length:  uint64(PingProtocol.MaxMsgSize),
    76  		Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
    77  			quitC := make(chan struct{})
    78  			pp := protocols.NewPeer(p, rw, PingProtocol)
    79  			log.Trace("running pss vprotocol", "peer", p, "outc", ping.OutC)
    80  			go func() {
    81  				for {
    82  					select {
    83  					case ispong := <-ping.OutC:
    84  						pp.Send(context.TODO(), &PingMsg{
    85  							Created: time.Now(),
    86  							Pong:    ispong,
    87  						})
    88  					case <-quitC:
    89  					}
    90  				}
    91  			}()
    92  			err := pp.Run(ping.pingHandler)
    93  			quitC <- struct{}{}
    94  			return err
    95  		},
    96  	}
    97  }