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 }