github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/p2pserver/sync/conn/conn.go (about)

     1  package conn
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"net"
     7  	"time"
     8  
     9  	"sync"
    10  
    11  	"github.com/sixexorg/magnetic-ring/log"
    12  	"github.com/sixexorg/magnetic-ring/p2pserver/common"
    13  )
    14  
    15  //Link used to establish
    16  type Link struct {
    17  	sync.Mutex
    18  	id        uint64
    19  	addr      string   // The address of the node
    20  	conn      net.Conn // Connect socket with the peer node
    21  	rlpconn   common.MsgReadWriter
    22  	port      uint16                  // The server port of the node
    23  	time      time.Time               // The latest time the node activity
    24  	recvChan  chan *common.MsgPayload //msgpayload channel
    25  	reqRecord map[string]int64        //Map RequestId to Timestamp, using for rejecting duplicate request in specific time
    26  }
    27  
    28  /*
    29  var (
    30  	msgPool = make(map[cm1.Hash]int64)
    31  	t       = cm1.NewTimingWheel(time.Second, 5)
    32  	m       sync.RWMutex
    33  )
    34  
    35  func init() {
    36  	go func() {
    37  		for {
    38  			select {
    39  			case <-t.After(time.Second * 1):
    40  				time := time.Now().Unix()
    41  				for k, v := range msgPool {
    42  					if v < time {
    43  						delete(msgPool, k)
    44  					}
    45  				}
    46  			}
    47  		}
    48  	}()
    49  }
    50  */
    51  func NewLink() *Link {
    52  	link := &Link{
    53  		reqRecord: make(map[string]int64, 0),
    54  	}
    55  	return link
    56  }
    57  
    58  //SetID set peer id to link
    59  func (that *Link) SetID(id uint64) {
    60  	that.id = id
    61  }
    62  
    63  //GetID return if from peer
    64  func (that *Link) GetID() uint64 {
    65  	return that.id
    66  }
    67  
    68  //If there is connection return true
    69  func (that *Link) Valid() bool {
    70  	return that.conn != nil
    71  }
    72  
    73  //set message channel for link layer
    74  func (that *Link) SetChan(msgchan chan *common.MsgPayload) {
    75  	that.recvChan = msgchan
    76  }
    77  
    78  //get address
    79  func (that *Link) GetAddr() string {
    80  	return that.addr
    81  }
    82  
    83  //set address
    84  func (that *Link) SetAddr(addr string) {
    85  	that.addr = addr
    86  }
    87  
    88  //set port number
    89  func (that *Link) SetPort(p uint16) {
    90  	that.port = p
    91  }
    92  
    93  //get port number
    94  func (that *Link) GetPort() uint16 {
    95  	return that.port
    96  }
    97  
    98  //get connection
    99  func (that *Link) GetConn() net.Conn {
   100  	return that.conn
   101  }
   102  
   103  //set connection
   104  func (that *Link) SetConn(conn net.Conn) {
   105  	that.conn = conn
   106  }
   107  
   108  //get connection
   109  func (that *Link) GetRLPConn() common.MsgReadWriter {
   110  	return that.rlpconn
   111  }
   112  
   113  //set connection
   114  func (that *Link) SetRLPConn(rlpconn common.MsgReadWriter) {
   115  	that.rlpconn = rlpconn
   116  }
   117  
   118  //record latest message time
   119  func (that *Link) UpdateRXTime(t time.Time) {
   120  	that.time = t
   121  }
   122  
   123  //GetRXTime return the latest message time
   124  func (that *Link) GetRXTime() time.Time {
   125  	return that.time
   126  }
   127  
   128  func (that *Link) RxHandle() error {
   129  	rlpmsg, err := that.rlpconn.ReadMsg()
   130  	if err != nil {
   131  		fmt.Println("that.rlpconn.ReadMsg occured error-->", err)
   132  		log.Warn("[p2p]error read from", "Addr", that.GetAddr(), "err", err.Error())
   133  		return err
   134  	}
   135  	if rlpmsg.Size > 10*1024*1024 {
   136  		// return errResp(ErrMsgTooLarge, "%v > %v", rlpmsg.Size, ProtocolMaxMsgSize)
   137  		log.Info("[p2p]error ErrMsgTooLarge", "Size", rlpmsg.Size, "SizeCount", 10*1024*1024)
   138  		return errors.New(" (()()()()")
   139  	}
   140  	defer rlpmsg.Discard()
   141  
   142  	codestr := common.TransCodeUToStr(rlpmsg.Code)
   143  
   144  	msg, err := common.MakeEmptyMessage(codestr)
   145  	if err != nil {
   146  		return err
   147  	}
   148  	if err := rlpmsg.Decode(msg); err != nil { //decode
   149  		return err
   150  	}
   151  	/*	h, err := rlpmsg.DistinctSk()
   152  		if err != nil {
   153  			fmt.Println("distinct msg err ", err)
   154  			return err
   155  		}
   156  		_, ok := msgPool[h]
   157  		if !ok {
   158  			msgPool[h] = time.Now().Add(time.Second * 60).Unix()
   159  		} else {
   160  			fmt.Println("repeat msg")
   161  			return errors.New("repeat msg")
   162  		}
   163  		fmt.Println("conn rxHandle pass")*/
   164  	if codestr == common.HEADERS_TYPE {
   165  		msg, err = common.BlkP2PHeaderToBlkHeader(msg.(*common.BlkP2PHeader))
   166  	} else if codestr == common.BLOCK_TYPE {
   167  		msg, err = common.TrsBlockToBlock(msg.(*common.TrsBlock))
   168  		// }else if codestr == common.INV_TYPE {
   169  	} else if codestr == common.TX_TYPE {
   170  		msg, err = common.P2PTrnToTrn(msg.(*common.P2PTrn))
   171  	} else if codestr == common.CONSENSUS_TYPE {
   172  		msg, err = common.P2PConsPldToConsensus(msg.(*common.P2PConsPld))
   173  	}
   174  
   175  	if err != nil {
   176  		return err
   177  	}
   178  
   179  	t := time.Now()
   180  	that.UpdateRXTime(t)
   181  
   182  	if !that.needSendMsg(msg) {
   183  		log.Debug("skip handle", "msgType", msg.CmdType(), "from", that.id)
   184  		return nil
   185  	}
   186  	that.addReqRecord(msg)
   187  	that.recvChan <- &common.MsgPayload{
   188  		Id:          that.id,
   189  		Addr:        that.addr,
   190  		PayloadSize: rlpmsg.Size,
   191  		Payload:     msg,
   192  	}
   193  	return nil
   194  }
   195  
   196  func (that *Link) Rx() {
   197  	for {
   198  		if err := that.RxHandle(); err != nil {
   199  			// p.Log().Debug("Ethereum message handling failed", "err", err)
   200  			log.Warn(" Link Rx", "err", err)
   201  			break
   202  		}
   203  	}
   204  	that.disconnectNotify()
   205  }
   206  
   207  //disconnectNotify push disconnect msg to channel // used
   208  func (that *Link) disconnectNotify() {
   209  	log.Debug("[p2p]call disconnectNotify for", "Addr", that.GetAddr())
   210  	that.CloseConn()
   211  
   212  	msg, _ := common.MakeEmptyMessage(common.DISCONNECT_TYPE)
   213  	discMsg := &common.MsgPayload{
   214  		Id:      that.id,
   215  		Addr:    that.addr,
   216  		Payload: msg,
   217  	}
   218  	that.recvChan <- discMsg
   219  }
   220  
   221  //close connection // used
   222  func (that *Link) CloseConn() {
   223  	if that.conn != nil {
   224  		that.conn.Close()
   225  		that.conn = nil
   226  	}
   227  }
   228  
   229  func (that *Link) Tx(msg common.Message) error {
   230  	err := common.Send(that.rlpconn, common.TransCodeStrToU(msg.CmdType()), msg)
   231  
   232  	if err != nil {
   233  		log.Warn("[p2p]error sending messge to", "Addr", that.GetAddr(), "msgType", msg.CmdType(), "err", err.Error())
   234  		that.disconnectNotify()
   235  		return err
   236  	}
   237  	return nil
   238  }
   239  
   240  //needSendMsg check whether the msg is needed to push to channel
   241  func (that *Link) needSendMsg(msg common.Message) bool {
   242  	that.Lock()
   243  	defer that.Unlock()
   244  
   245  	if msg.CmdType() != common.GET_DATA_TYPE {
   246  		return true
   247  	}
   248  	var dataReq = msg.(*common.DataReq)
   249  	reqID := fmt.Sprintf("%x%s", dataReq.DataType, dataReq.Hash.String())
   250  	now := time.Now().Unix()
   251  
   252  	if t, ok := that.reqRecord[reqID]; ok {
   253  		if int(now-t) < common.REQ_INTERVAL {
   254  			return false
   255  		}
   256  	}
   257  	return true
   258  }
   259  
   260  //addReqRecord add request record by removing outdated request records
   261  func (that *Link) addReqRecord(msg common.Message) {
   262  	that.Lock()
   263  	defer that.Unlock()
   264  
   265  	if msg.CmdType() != common.GET_DATA_TYPE {
   266  		return
   267  	}
   268  	now := time.Now().Unix()
   269  	if len(that.reqRecord) >= common.MAX_REQ_RECORD_SIZE-1 {
   270  		for id := range that.reqRecord {
   271  			t := that.reqRecord[id]
   272  			if int(now-t) > common.REQ_INTERVAL {
   273  				delete(that.reqRecord, id)
   274  			}
   275  		}
   276  	}
   277  	var dataReq = msg.(*common.DataReq)
   278  	reqID := fmt.Sprintf("%x%s", dataReq.DataType, dataReq.Hash.String())
   279  	that.reqRecord[reqID] = now
   280  }