github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/p2pserver/discover/udp_circle.go (about) 1 package discover 2 3 import ( 4 "errors" 5 "fmt" 6 "net" 7 "time" 8 9 comm "github.com/sixexorg/magnetic-ring/common" 10 "github.com/sixexorg/magnetic-ring/log" 11 ) 12 13 const ( 14 maxNeighborsCircle = 10 15 REQPEERORGNUM = 200 16 ) 17 18 // Errors 19 var ( 20 errCirclePacketTooSmall = errors.New("circle data too small") 21 // errBadHash = errors.New("bad hash") 22 // errExpired = errors.New("expired") 23 // errUnsolicitedReply = errors.New("unsolicited reply") 24 errUnknownCircle = errors.New("unknown circle") 25 // errTimeout = errors.New("RPC timeout") 26 // errClockWarp = errors.New("reply deadline too far in the future") 27 // errClosed = errors.New("socket closed") 28 ) 29 30 // RPC request structures 31 type ( 32 sendcircle struct { 33 Version uint 34 From, To rpcEndpoint 35 SrcOrgID comm.Address 36 OwnID uint64 37 BAdd bool 38 Expiration uint64 39 } 40 41 // pong is the reply to ping. 42 rtncircle struct { 43 // This field should mirror the UDP envelope address 44 // of the ping packet, which provides a way to discover the 45 // the external address (after NAT). 46 To rpcEndpoint 47 48 ReplyTok []byte // This contains the hash of the ping packet. 49 Expiration uint64 // Absolute timestamp at which the packet becomes invalid. 50 } 51 52 sendConnect struct { 53 Version uint 54 From, To rpcEndpoint 55 OwnID, RemoteID uint64 56 BConnect bool 57 BStellarNode bool 58 Expiration uint64 59 } 60 61 rtnConnect struct { 62 // This field should mirror the UDP envelope address 63 // of the ping packet, which provides a way to discover the 64 // the external address (after NAT). 65 To rpcEndpoint 66 67 ReplyTok []byte // This contains the hash of the ping packet. 68 Expiration uint64 // Absolute timestamp at which the packet becomes invalid. 69 } 70 71 findcircle struct { 72 // Target CirclseID // doesn't need to be an actual public key 73 Target comm.Address 74 Expiration uint64 75 } 76 77 neighborscircle struct { 78 Nodes []rpcNode 79 Num uint64 80 Expiration uint64 81 } 82 83 reqPeerOrg struct { 84 Target NodeID // doesn't need to be an actual public key 85 Expiration uint64 86 } 87 88 rntPeerOrg struct { 89 Num uint64 90 OwnID uint64 91 Orgs []comm.Address 92 Expiration uint64 93 } 94 95 reqPeerConnect struct { 96 Target NodeID // doesn't need to be an actual public key 97 Expiration uint64 98 } 99 100 // reply to findnode 101 rntPeerConnect struct { 102 Num uint64 103 OwnID uint64 104 RemoteID []uint64 105 Expiration uint64 106 } 107 108 connectCircuOrg struct { 109 From rpcEndpoint 110 OrgID comm.Address 111 ConnectNode rpcNode 112 Expiration uint64 113 } 114 115 rtnCircuOrg struct { 116 Expiration uint64 117 } 118 ) 119 120 func (t *udp) sendcircle(ndoe, srcnode *Node, SrcOrgID comm.Address, ownid uint64, badd bool) error { 121 // TODO: maybe check for ReplyTo field in callback to measure RTT 122 //fmt.Println(" ****** udp sendcircle start ...... badd:",badd) 123 toid, toaddr := ndoe.ID, ndoe.addr() 124 errc := t.pending(toid, rtncirclePacket, func(interface{}) bool { return true }) 125 t.send(toaddr, sendcirclePacket, &sendcircle{ 126 Version: Version, 127 From: t.ourEndpoint, 128 // To: makeEndpoint(toaddr, 0), // TODO: maybe use known TCP port from DB 129 BAdd: badd, 130 OwnID: ownid, 131 SrcOrgID: SrcOrgID, 132 Expiration: uint64(time.Now().Add(expiration).Unix()), 133 }) 134 errs := <-errc 135 return errs 136 } 137 138 func (t *udp) findcircle(toid NodeID, toaddr *net.UDPAddr, target comm.Address) ([]*Node, error) { 139 //fmt.Println(" ******* udp findcircle ...... ") 140 nodes := make([]*Node, 0) 141 nreceived := uint64(0) 142 total := uint64(0) 143 errc := t.pending(toid, neighborscirclePacket, func(r interface{}) bool { 144 reply := r.(*neighborscircle) 145 //fmt.Println(" ***** len(reply.Nodes):",len(reply.Nodes)) 146 //fmt.Println(" ***** reply.Nodes:",reply.Nodes) 147 total = reply.Num 148 for _, rn := range reply.Nodes { 149 nreceived++ 150 // n, err := t.nodeFromRPC(toaddr, rn) 151 n, err := t.nodeFromRPC2(toaddr, rn) 152 153 if err != nil { 154 log.Trace("Invalid neighbor node received", "ip", rn.IP, "addr", toaddr, "err", err) 155 //fmt.Println(" *** findcircle received", "ip", rn.IP, "addr", toaddr, "err", err) 156 continue 157 } 158 nodes = append(nodes, n) 159 } 160 return nreceived >= total 161 }) 162 t.send(toaddr, findcirclePacket, &findcircle{ 163 Target: target, 164 Expiration: uint64(time.Now().Add(expiration).Unix()), 165 }) 166 err := <-errc 167 return nodes, err 168 } 169 170 func (t *udp) sendConnectInfo(ndoe, srcnode *Node, ownid, remoteid uint64, bconnect, bstellar bool) error { 171 // TODO: maybe check for ReplyTo field in callback to measure RTT 172 //fmt.Println(" ****** udp sendConnect start ...... bconnect:",bconnect) 173 //defer fmt.Println(" ****** udp sendConnect end ...... bconnect:", bconnect) 174 175 toid, toaddr := ndoe.ID, ndoe.addr() 176 errc := t.pending(toid, rtnconnectPacket, func(interface{}) bool { return true }) 177 eerr := t.send(toaddr, sendConnectPacket, &sendConnect{ 178 Version: Version, 179 From: t.ourEndpoint, 180 OwnID: ownid, 181 RemoteID: remoteid, 182 BConnect: bconnect, 183 BStellarNode: bstellar, 184 Expiration: uint64(time.Now().Add(expiration).Unix()), 185 }) 186 187 if eerr!=nil { 188 fmt.Println("🐞 🐞 🐞 🐞 🐞 🐞 🐞 🐞-->",eerr) 189 } 190 191 return <-errc 192 } 193 194 func (t *udp) reqPeerOrg(toid NodeID, toaddr *net.UDPAddr, node *Node) (*rtnTabPeerOrg, error) { 195 //fmt.Println(" ******* udp reqPeerOrg ...... ") 196 orgs := new(rtnTabPeerOrg) 197 orgs.orgsId = make([]comm.Address, 0) 198 orgs.node = node 199 200 receiveNum := uint64(0) 201 total := uint64(0) 202 203 errc := t.pending(toid, rntPeerOrgPacket, func(r interface{}) bool { 204 reply := r.(*rntPeerOrg) 205 //fmt.Println(" ***** len(reply.Nodes):",len(reply.Orgs)) 206 total = reply.Num 207 orgs.ownId = reply.OwnID 208 // for _, rn := range reply.Orgs { 209 orgs.orgsId = append(orgs.orgsId, reply.Orgs...) 210 receiveNum = receiveNum + uint64(len(reply.Orgs)) 211 // } 212 return receiveNum >= total 213 }) 214 t.send(toaddr, reqPeerOrgPacket, &reqPeerOrg{ 215 Target: toid, 216 Expiration: uint64(time.Now().Add(expiration).Unix()), 217 }) 218 err := <-errc 219 //fmt.Println(" *8888888* udp reqPeerConnect orgs:",*orgs) 220 return orgs, err 221 } 222 223 func (t *udp) reqPeerConnect(toid NodeID, toaddr *net.UDPAddr, node *Node) (*rtnTabPeerConnect, error) { 224 //fmt.Println(" ******* udp reqPeerConnect ...... ") 225 receiveNum := uint64(0) 226 total := uint64(0) 227 result := new(rtnTabPeerConnect) 228 result.remotesID = make([]uint64, 0) 229 result.node = node 230 231 errc := t.pending(toid, rntPeerConnectPacket, func(r interface{}) bool { 232 reply := r.(*rntPeerConnect) 233 //fmt.Println(" ***** reqPeerConnect len(reply.Peer):",len(reply.RemoteID)) 234 total = reply.Num 235 result.ownId = reply.OwnID 236 for _, rn := range reply.RemoteID { 237 result.remotesID = append(result.remotesID, rn) 238 receiveNum = receiveNum + 1 239 } 240 return receiveNum >= total 241 }) 242 t.send(toaddr, reqPeerConnectPacket, &reqPeerConnect{ 243 Target: toid, 244 Expiration: uint64(time.Now().Add(expiration).Unix()), 245 }) 246 err := <-errc 247 //fmt.Println(" *8888888* udp reqPeerConnect result:",*result) 248 return result, err 249 } 250 251 func (t *udp) connectCircuOrg(ndoe, connectnode *Node, orgid comm.Address) error { 252 // TODO: maybe check for ReplyTo field in callback to measure RTT 253 //fmt.Println(" ****** udp connectCircuOrg start ...... ") 254 defer fmt.Println(" ****** udp connectCircuOrg end ...... ") 255 toid, toaddr := ndoe.ID, ndoe.addr() 256 errc := t.pending(toid, rtnCircuOrgPacket, func(interface{}) bool { return true }) 257 t.send(toaddr, connectCircuOrgPacket, &connectCircuOrg{ 258 From: t.ourEndpoint, 259 OrgID: orgid, 260 ConnectNode: nodeToRPC(connectnode), // 261 Expiration: uint64(time.Now().Add(expiration).Unix()), 262 }) 263 return <-errc 264 } 265 266 func (req *sendcircle) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 267 if expired(req.Expiration) { 268 return errExpired 269 } 270 t.send(from, rtncirclePacket, &rtncircle{ 271 To: makeEndpoint(from, req.From.TCP), 272 ReplyTok: mac, 273 Expiration: uint64(time.Now().Add(expiration).Unix()), 274 }) 275 276 // // add circle 277 // fmt.Println(" ***** sendcircle handle from:",from) 278 // fmt.Println(" ***** sendcircle handle fromID:",fromID) 279 // fmt.Println(" ***** sendcircle handle req.From:",req.From) 280 n := NewNode(fromID, from.IP, uint16(from.Port), req.From.TCP) 281 if req.SrcOrgID == t.stellarNodeID { 282 go t.stellarNode(n, req.SrcOrgID, req.OwnID, req.BAdd) 283 } else { 284 go t.setOrgs(n, req.SrcOrgID, req.OwnID, req.BAdd) 285 } 286 287 return nil 288 } 289 290 func (req *sendcircle) name() string { return "sendcircle/v4" } 291 292 func (req *rtncircle) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 293 if expired(req.Expiration) { 294 return errExpired 295 } 296 if !t.handleReply(fromID, rtncirclePacket, req) { 297 return errUnsolicitedReply 298 } 299 return nil 300 } 301 302 func (req *rtncircle) name() string { return "rtncircle/v4" } 303 304 func (req *findcircle) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 305 //fmt.Println(" ****** findcircle handle ...... ") 306 if expired(req.Expiration) { 307 return errExpired 308 } 309 // if t.db.node(fromID) == nil { 310 // return errUnknownNode 311 // } 312 313 var err error 314 targetData := make([]*Node, 0) 315 if req.Target == t.stellarNodeID { 316 targetData, err = t.getStellar() 317 } else { 318 targetData, err = t.getCircle(req.Target, maxNeighborsCircle) 319 } 320 321 if err != nil { 322 return errUnknownCircle 323 } 324 325 if len(targetData) <= 0 { 326 return errCirclePacketTooSmall 327 } 328 329 p := neighborscircle{ 330 Num: uint64(len(targetData)), 331 Expiration: uint64(time.Now().Add(expiration).Unix()), 332 } 333 // Send neighbors in chunks with at most maxNeighbors per packet 334 // to stay below the 1280 byte limit. 335 for i, n := range targetData { 336 // errip := netutil.CheckRelayIP(from.IP, n.IP) 337 // if errip != nil { 338 // fmt.Printf(" ***** CheckRelayIP from.IP:%v,n.IP:%v\n",from.IP,n.IP) 339 // fmt.Println(" ****** CheckRelayIP error errip:",errip) 340 // continue 341 // } 342 p.Nodes = append(p.Nodes, nodeToRPC(n)) 343 if len(p.Nodes) == maxNeighbors || i == len(targetData)-1 { 344 t.send(from, neighborscirclePacket, &p) 345 p.Nodes = p.Nodes[:0] 346 } 347 } 348 return nil 349 } 350 351 func (req *findcircle) name() string { return "FINDCIRCLE/v4" } 352 353 func (req *neighborscircle) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 354 if expired(req.Expiration) { 355 return errExpired 356 } 357 //fmt.Println(" ******** neighborscircle handle len(req.Nodes):",len(req.Nodes)) 358 err := t.handleReply(fromID, neighborscirclePacket, req) 359 if !err { 360 //fmt.Println(" ****** neighborscircle handle err:",err) 361 return errUnsolicitedReply 362 } 363 return nil 364 } 365 366 func (req *neighborscircle) name() string { return "NEIGHBORSCIRCLE/v4" } 367 368 func (req *sendConnect) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 369 if expired(req.Expiration) { 370 return errExpired 371 } 372 t.send(from, rtnconnectPacket, &rtnConnect{ 373 To: makeEndpoint(from, req.From.TCP), 374 ReplyTok: mac, 375 Expiration: uint64(time.Now().Add(expiration).Unix()), 376 }) 377 378 // add circle 379 // fmt.Println(" ***** sendConnect handle from:",from) 380 // fmt.Println(" ***** sendConnect handle fromID:",fromID) 381 // fmt.Println(" ***** sendConnect handle req.From:",req.From) 382 if !req.BStellarNode { 383 n := NewNode(fromID, from.IP, uint16(from.Port), req.From.TCP) 384 go t.setConnect(req.OwnID, req.RemoteID, req.BConnect, n) // 385 if !req.BConnect { 386 go t.setConnect(req.RemoteID, req.OwnID, req.BConnect, n) // 387 } else if req.BConnect { 388 // go t.setConnect(req.RemoteID,req.OwnID,req.BConnect,nil) // 389 } 390 } else { 391 t.stellarInspectDis(req.RemoteID) 392 } 393 394 return nil 395 } 396 397 func (req *sendConnect) name() string { return "sendConnect/v4" } 398 399 func (req *rtnConnect) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 400 if expired(req.Expiration) { 401 return errExpired 402 } 403 if !t.handleReply(fromID, rtnconnectPacket, req) { 404 return errUnsolicitedReply 405 } 406 return nil 407 } 408 409 func (req *rtnConnect) name() string { return "rtnConnect/v4" } 410 411 func (req *reqPeerOrg) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 412 //fmt.Println(" ****** reqPeerOrg handle ...... ") 413 if expired(req.Expiration) { 414 return errExpired 415 } 416 417 ownID, orgsId := t.callPeerOrgInfo() 418 419 p := rntPeerOrg{ 420 Expiration: uint64(time.Now().Add(expiration).Unix()), 421 Num: uint64(len(orgsId)), 422 OwnID: ownID, 423 } 424 // Send neighbors in chunks with at most maxNeighbors per packet 425 // to stay below the 1280 byte limit. 426 if len(orgsId) > 0 { 427 for i, n := range orgsId { 428 p.Orgs = append(p.Orgs, n) 429 if len(p.Orgs) == maxPeerOrg || i == len(orgsId)-1 { 430 t.send(from, rntPeerOrgPacket, &p) 431 p.Orgs = p.Orgs[:0] 432 } 433 } 434 } else if len(orgsId) <= 0 { 435 t.send(from, rntPeerOrgPacket, &p) 436 } 437 return nil 438 } 439 440 func (req *reqPeerOrg) name() string { return "reqPeerOrg/v4" } 441 442 func (req *rntPeerOrg) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 443 if expired(req.Expiration) { 444 return errExpired 445 } 446 // fmt.Println(" ******** rntPeerOrg handle len(req.Nodes):",len(req.)) 447 err := t.handleReply(fromID, rntPeerOrgPacket, req) 448 if !err { 449 //fmt.Println(" ****** rntPeerOrg handle err:",err) 450 return errUnsolicitedReply 451 } 452 return nil 453 } 454 455 func (req *rntPeerOrg) name() string { return "rntPeerOrg/v4" } 456 457 func (req *reqPeerConnect) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 458 fmt.Println(" ****** reqPeerConnect handle ...... ") 459 if expired(req.Expiration) { 460 return errExpired 461 } 462 // targetData := new(rtnTabPeerConnect) 463 // var err error 464 ownID, remotesID := t.callPeerConnectInfo() 465 466 p := rntPeerConnect{ 467 Expiration: uint64(time.Now().Add(expiration).Unix()), 468 Num: uint64(len(remotesID)), 469 OwnID: ownID, 470 } 471 // Send neighbors in chunks with at most maxNeighbors per packet 472 // to stay below the 1280 byte limit. 473 if len(remotesID) > 0 { 474 for i, n := range remotesID { 475 p.RemoteID = append(p.RemoteID, n) 476 if len(p.RemoteID) == maxPeerOrg || i == len(remotesID)-1 { 477 t.send(from, rntPeerConnectPacket, &p) 478 p.RemoteID = p.RemoteID[:0] 479 } 480 } 481 } else if len(remotesID) <= 0 { 482 t.send(from, rntPeerConnectPacket, &p) 483 } 484 return nil 485 } 486 487 func (req *reqPeerConnect) name() string { return "reqPeerConnect/v4" } 488 489 func (req *rntPeerConnect) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 490 if expired(req.Expiration) { 491 return errExpired 492 } 493 // fmt.Println(" ******** rntPeerOrg handle len(req.Nodes):",len(req.)) 494 err := t.handleReply(fromID, rntPeerConnectPacket, req) 495 if !err { 496 fmt.Println(" ****** rntPeerConnect handle err:", err) 497 return errUnsolicitedReply 498 } 499 return nil 500 } 501 502 func (req *rntPeerConnect) name() string { return "rntPeerConnect/v4" } 503 504 // circu 505 func (req *connectCircuOrg) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 506 fmt.Println(" ****** connectCircuOrg handle ...... ") 507 if expired(req.Expiration) { 508 return errExpired 509 } 510 511 n := NewNode(fromID, from.IP, uint16(from.Port), req.From.TCP) // bootnode 512 destnode, err := t.nodeFromRPC(n.addr(), req.ConnectNode) //dest node 513 if err == nil { 514 t.callSendConnectOrg(destnode, req.OrgID) 515 } 516 517 p := rtnCircuOrg{Expiration: uint64(time.Now().Add(expiration).Unix())} 518 519 t.send(from, rtnCircuOrgPacket, &p) 520 return nil 521 } 522 523 func (req *connectCircuOrg) name() string { return "connectCircuOrg/v4" } 524 525 func (req *rtnCircuOrg) handle(t *udp, from *net.UDPAddr, fromID NodeID, mac []byte) error { 526 if expired(req.Expiration) { 527 return errExpired 528 } 529 // fmt.Println(" ******** rntPeerOrg handle len(req.Nodes):",len(req.)) 530 err := t.handleReply(fromID, rtnCircuOrgPacket, req) 531 if !err { 532 fmt.Println(" ****** rtnCircuOrg handle err:", err) 533 return errUnsolicitedReply 534 } 535 return nil 536 } 537 538 func (req *rtnCircuOrg) name() string { return "rtnCircuOrg/v4" }