github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/client/network/core.go (about) 1 package network 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "encoding/binary" 7 "encoding/hex" 8 "errors" 9 "fmt" 10 "net" 11 "strings" 12 "sync" 13 "sync/atomic" 14 "time" 15 16 "github.com/piotrnar/gocoin/client/common" 17 "github.com/piotrnar/gocoin/client/network/peersdb" 18 "github.com/piotrnar/gocoin/lib/btc" 19 "github.com/piotrnar/gocoin/lib/others/sys" 20 ) 21 22 const ( 23 AskAddrsEvery = (5 * time.Minute) 24 MaxAddrsPerMessage = 500 25 SendBufSize = 16 * 1024 * 1024 // If you'd have this much in the send buffer, disconnect the peer 26 SendBufMask = SendBufSize - 1 27 28 GetHeadersTimeout = 2 * time.Minute // Timeout to receive headers 29 VersionMsgTimeout = 20 * time.Second // Timeout to receive the version message after connecting 30 TCPDialTimeout = 20 * time.Second // If it does not connect within this time, assume it dead 31 NoDataTimeout = 5 * time.Minute // If no data received within this time, disconnect 32 33 MIN_PROTO_VERSION = 209 34 35 HammeringMinReconnect = 20 * time.Minute // If any incoming peer reconnects in below this time, ban it 36 HammeringMaxAllowedCount = 5 // If reconnecting more than this many times within the time above, ban the IP 37 HammeringExpirePeriod = time.Minute // Expite Hammering history interval 38 39 ExpireCachedAfter = 20 * time.Minute /*If a block stays in the cache for that long, drop it*/ 40 41 MAX_PEERS_BLOCKS_IN_PROGRESS = 500 42 MAX_BLOCKS_FORWARD_CNT = 5000 // Never ask for a block higher than current top + this value 43 MAX_GETDATA_FORWARD = 2e6 // Download up to 2MB forward (or one block) 44 45 MAINTANENCE_PERIOD = time.Minute 46 47 MAX_INV_HISTORY = 500 48 49 TxsCounterPeriod = 6 * time.Second // how long for one tick 50 TxsCounterBufLen = 60 // how many ticks 51 OnlineImmunityMinutes = int(TxsCounterBufLen * TxsCounterPeriod / time.Minute) 52 53 PeerTickPeriod = 100 * time.Millisecond // run the peer's tick not more often than this 54 InvsFlushPeriod = 10 * time.Millisecond // send all the pending invs to the peer not more often than this 55 56 MAX_GETMP_TXS = 1e6 57 ) 58 59 var ( 60 Mutex_net sync.Mutex 61 OpenCons map[uint64]*OneConnection = make(map[uint64]*OneConnection) 62 InConsActive, OutConsActive uint32 63 LastConnId uint32 64 nonce [8]byte 65 66 // Hammering protection (peers that keep re-connecting) map IPv4 => UnixTime 67 HammeringMutex sync.Mutex 68 RecentlyDisconencted map[[4]byte]*RecentlyDisconenctedType = make(map[[4]byte]*RecentlyDisconenctedType) 69 ) 70 71 type RecentlyDisconenctedType struct { 72 time.Time 73 Count uint 74 Why string 75 } 76 77 type NetworkNodeStruct struct { 78 Version uint32 79 Services uint64 80 Timestamp uint64 81 Height uint32 82 Agent string 83 DoNotRelayTxs bool 84 ReportedIp4 uint32 85 SendHeaders bool 86 Nonce [8]byte 87 88 // BIP152: 89 SendCmpctVer uint64 90 HighBandwidth bool 91 } 92 93 type ConnectionStatus struct { 94 Incomming bool 95 ConnectedAt time.Time 96 VersionReceived bool 97 LastBtsRcvd, LastBtsSent uint32 98 LastCmdRcvd, LastCmdSent string 99 LastDataGot time.Time // if we have no data for some time, we abort this conenction 100 Ticks uint64 101 OurGetAddrDone bool // Whether we shoudl issue another "getaddr" 102 103 AllHeadersReceived bool // keep sending getheaders until this is not set 104 LastHeadersEmpty bool 105 TotalNewHeadersCount int 106 GetHeadersInProgress bool 107 GetHeadersTimeOutAt time.Time 108 GetHeadersSentAtPingCnt uint64 109 LastHeadersHeightAsk uint32 110 GetBlocksDataNow bool 111 112 LastSent time.Time 113 MaxSentBufSize int 114 115 PingHistory [PingHistoryLength]int 116 PingHistoryIdx int 117 InvsRecieved uint64 118 119 BytesReceived, BytesSent uint64 120 Counters map[string]uint64 121 122 GetAddrDone bool 123 MinFeeSPKB int64 // BIP 133 124 125 TxsReceived int // During last hour 126 127 IsSpecial bool // Special connections get more debgs and are not being automatically dropped 128 IsGocoin bool 129 Debug bool 130 131 Authorized bool 132 AuthMsgGot uint 133 AuthAckGot bool 134 135 LastMinFeePerKByte uint64 136 137 PingSentCnt uint64 138 BlocksExpired uint64 139 140 NewAddrsRcvd uint64 141 AddrMsgsRcvd uint64 142 143 ChainSynchronized bool // Initiated by "auth" or "autack" message (gocoin specific commmands) 144 } 145 146 type ConnInfo struct { 147 ID uint32 148 PeerIp string 149 150 NetworkNodeStruct 151 ConnectionStatus 152 153 BytesToSend int 154 BlocksInProgress int 155 InvsToSend int 156 AveragePing int 157 InvsDone int 158 BlocksReceived int 159 GetMPInProgress bool 160 161 LocalAddr, RemoteAddr string 162 163 // This one is only set inside webui's hnadler (for sorted connections) 164 HasImmunity bool 165 } 166 167 type OneConnection struct { 168 // Source of this IP: 169 *peersdb.PeerAddr 170 ConnID uint32 171 172 sync.Mutex // protects concurent access to any fields inside this structure 173 174 broken bool // flag that the conenction has been broken / shall be disconnected 175 dead bool // If set the alive time in PeersDB will ne moved back 176 why_disconnected string 177 banit bool // Ban this client after disconnecting 178 ban_reason string 179 misbehave int // When it reaches 1000, ban it 180 181 net.Conn 182 183 // TCP connection data: 184 X ConnectionStatus 185 186 Node NetworkNodeStruct // Data from the version message 187 188 // Messages reception state machine: 189 recv struct { 190 hdr [24]byte 191 hdr_len int 192 pl_len uint32 // length taken from the message header 193 cmd string 194 dat []byte 195 datlen uint32 196 } 197 LastMsgTime time.Time 198 unfinished_getdata *bytes.Buffer 199 200 InvDone struct { 201 Map map[uint64]uint32 202 History []uint64 203 Idx int 204 } 205 206 // Message sending state machine: 207 sendBuf [SendBufSize]byte 208 SendBufProd, SendBufCons int 209 210 // Statistics: 211 PendingInvs []*[36]byte // List of pending INV to send and the mutex protecting access to it 212 sendInvsNow sys.SyncBool 213 214 GetBlockInProgress map[BIDX]*oneBlockDl 215 216 // Ping stats 217 LastPingSent time.Time 218 PingInProgress []byte 219 lastSec int64 220 221 counters map[string]uint64 222 223 blocksreceived []time.Time 224 nextMaintanence time.Time 225 nextGetData time.Time 226 keepBlocksOver int 227 228 // we need these three below to count txs received only during last hour 229 txsCur int 230 txsCha chan int 231 txsNxt time.Time 232 233 writing_thread_done sync.WaitGroup 234 writing_thread_push chan bool 235 236 GetMP chan bool 237 } 238 239 type BIDX [btc.Uint256IdxLen]byte 240 241 type oneBlockDl struct { 242 hash *btc.Uint256 243 start time.Time 244 col *CmpctBlockCollector 245 SentAtPingCnt uint64 246 } 247 248 type BCmsg struct { 249 cmd string 250 pl []byte 251 } 252 253 func NewConnection(ad *peersdb.PeerAddr) (c *OneConnection) { 254 c = new(OneConnection) 255 c.PeerAddr = ad 256 c.GetBlockInProgress = make(map[BIDX]*oneBlockDl) 257 c.ConnID = atomic.AddUint32(&LastConnId, 1) 258 c.counters = make(map[string]uint64) 259 c.InvDone.Map = make(map[uint64]uint32, MAX_INV_HISTORY) 260 c.GetMP = make(chan bool, 1) 261 return 262 } 263 264 func (v *OneConnection) cntLockInc(name string) { 265 if !common.NoCounters.Get() { 266 v.Mutex.Lock() 267 v.counters[name]++ 268 v.Mutex.Unlock() 269 } 270 } 271 272 func (v *OneConnection) cntInc(name string) { 273 if !common.NoCounters.Get() { 274 v.counters[name]++ 275 } 276 } 277 278 func (v *OneConnection) cntAdd(name string, val uint64) { 279 if !common.NoCounters.Get() { 280 v.counters[name] += val 281 } 282 } 283 284 // MutexSetBool does a mutex protected assignment of val to addr. 285 func (v *OneConnection) MutexSetBool(addr *bool, val bool) { 286 v.Mutex.Lock() 287 *addr = val 288 v.Mutex.Unlock() 289 } 290 291 // MutexGetBool does a mutex protected read of the value of addr and returns it. 292 func (v *OneConnection) MutexGetBool(addr *bool) (val bool) { 293 v.Mutex.Lock() 294 val = *addr 295 v.Mutex.Unlock() 296 return 297 } 298 299 // call it with locked mutex! 300 func (v *OneConnection) BytesToSent() int { 301 if v.SendBufProd >= v.SendBufCons { 302 return v.SendBufProd - v.SendBufCons 303 } else { 304 return v.SendBufProd + SendBufSize - v.SendBufCons 305 } 306 } 307 308 // call it with unlocked mutex! 309 func (c *OneConnection) SendingPaused() (res bool) { 310 c.Mutex.Lock() 311 res = c.BytesToSent() > SendBufSize/2 312 c.Mutex.Unlock() 313 return 314 } 315 316 func (v *OneConnection) GetStats(res *ConnInfo) { 317 v.Mutex.Lock() 318 res.ID = v.ConnID 319 res.PeerIp = v.PeerAddr.Ip() 320 if v.Conn != nil { 321 res.LocalAddr = v.Conn.LocalAddr().String() 322 res.RemoteAddr = v.Conn.RemoteAddr().String() 323 } 324 res.NetworkNodeStruct = v.Node 325 res.ConnectionStatus = v.X 326 res.BytesToSend = v.BytesToSent() 327 res.BlocksInProgress = len(v.GetBlockInProgress) 328 res.InvsToSend = len(v.PendingInvs) 329 res.AveragePing = v.GetAveragePing() 330 331 res.Counters = make(map[string]uint64, len(v.counters)) 332 for k, v := range v.counters { 333 res.Counters[k] = v 334 } 335 336 res.InvsDone = len(v.InvDone.History) 337 res.BlocksReceived = len(v.blocksreceived) 338 res.GetMPInProgress = len(v.GetMP) != 0 339 340 v.Mutex.Unlock() 341 } 342 343 func (c *OneConnection) SendRawMsg(cmd string, pl []byte) (e error) { 344 c.Mutex.Lock() 345 346 /*if c.X.Debug { 347 fmt.Println(c.ConnID, "sent", cmd, len(pl)) 348 }*/ 349 350 if !c.broken { 351 // we never allow the buffer to be totally full because then producer would be equal consumer 352 if bytes_left := SendBufSize - c.BytesToSent(); bytes_left <= len(pl)+24 { 353 c.Mutex.Unlock() 354 println(c.PeerAddr.Ip(), c.Node.Version, c.Node.Agent, "Peer Send Buffer Overflow @", 355 cmd, bytes_left, len(pl)+24, c.SendBufProd, c.SendBufCons, c.BytesToSent()) 356 c.DoS("SendBufferOverflow") 357 common.CountSafe("PeerSendOverflow") 358 return errors.New("send buffer overflow") 359 } 360 361 if !common.NoCounters.Get() { 362 ssent := "sent_" + cmd 363 ssbts := "sbts_" + cmd 364 c.cntInc(ssent) 365 c.cntAdd(ssbts, uint64(len(pl))) 366 common.CountSafe(ssent) 367 common.CountSafeAdd(ssbts, uint64(len(pl))) 368 } 369 var sbuf [24]byte 370 371 c.X.LastCmdSent = cmd 372 c.X.LastBtsSent = uint32(len(pl)) 373 374 binary.LittleEndian.PutUint32(sbuf[0:4], common.Version) 375 copy(sbuf[0:4], common.Magic[:]) 376 copy(sbuf[4:16], cmd) 377 binary.LittleEndian.PutUint32(sbuf[16:20], uint32(len(pl))) 378 379 sh := btc.Sha2Sum(pl[:]) 380 copy(sbuf[20:24], sh[:4]) 381 382 c.append_to_send_buffer(sbuf[:]) 383 c.append_to_send_buffer(pl) 384 385 if x := c.BytesToSent(); x > c.X.MaxSentBufSize { 386 c.X.MaxSentBufSize = x 387 } 388 } 389 c.Mutex.Unlock() 390 select { 391 case c.writing_thread_push <- true: 392 default: 393 } 394 return 395 } 396 397 // append_to_send_buffer assumes that there is enough room inside sendBuf. 398 func (c *OneConnection) append_to_send_buffer(d []byte) { 399 room_left := SendBufSize - c.SendBufProd 400 if room_left >= len(d) { 401 copy(c.sendBuf[c.SendBufProd:], d) 402 } else { 403 copy(c.sendBuf[c.SendBufProd:], d[:room_left]) 404 copy(c.sendBuf[:], d[room_left:]) 405 } 406 c.SendBufProd = (c.SendBufProd + len(d)) & SendBufMask 407 } 408 409 func (c *OneConnection) Disconnect(dead bool, why string) { 410 c.Mutex.Lock() 411 if c.X.Debug { 412 print("Disconnect " + c.PeerAddr.Ip() + " (" + c.Node.Agent + ") because -" + why + "-\n> ") 413 //println("LastCmdSent:", c.X.LastCmdSent, c.X.LastBtsSent, " LastCmdRcvd:", c.X.LastCmdRcvd, c.X.LastBtsRcvd) 414 } 415 c.dead = dead 416 c.broken = true 417 c.why_disconnected = why 418 c.Mutex.Unlock() 419 } 420 421 func (c *OneConnection) IsBroken() (res bool) { 422 c.Mutex.Lock() 423 res = c.broken 424 c.Mutex.Unlock() 425 return 426 } 427 428 func (c *OneConnection) DoS(why string) { 429 common.CountSafe("Ban" + why) 430 c.Mutex.Lock() 431 if c.X.Debug || c.X.Authorized { 432 print("BAN " + c.PeerAddr.Ip() + " (" + c.Node.Agent + ") because " + why + "\n> ") 433 } 434 c.banit = true 435 c.ban_reason = why 436 c.broken = true 437 c.Mutex.Unlock() 438 } 439 440 func (c *OneConnection) Misbehave(why string, how_much int) (res bool) { 441 c.Mutex.Lock() 442 if c.X.Debug || c.X.Authorized { 443 print("Misbehave " + c.PeerAddr.Ip() + " (" + c.Node.Agent + ") because " + why + "\n> ") 444 } 445 if !c.banit { 446 common.CountSafe("Bad" + why) 447 c.misbehave += how_much 448 if c.misbehave >= 1000 { 449 common.CountSafe("BanMisbehave") 450 res = true 451 c.banit = true 452 c.ban_reason = "Bad" + why 453 c.broken = true 454 //print("Ban " + c.PeerAddr.Ip() + " (" + c.Node.Agent + ") because " + why + "\n> ") 455 } 456 } else { 457 common.CountSafe("Misb" + why) 458 } 459 c.Mutex.Unlock() 460 return 461 } 462 463 func (c *OneConnection) HandleError(e error) error { 464 if nerr, ok := e.(net.Error); ok && nerr.Timeout() { 465 //fmt.Println("Just a timeout - ignore") 466 return nil 467 } 468 c.recv.hdr_len = 0 469 c.recv.dat = nil 470 c.Disconnect(true, "Error:"+e.Error()) 471 return e 472 } 473 474 func (c *OneConnection) FetchMessage() (ret *BCmsg, timeout_or_data bool) { 475 var e error 476 var n int 477 478 for c.recv.hdr_len < 24 { 479 n, e = common.SockRead(c.Conn, c.recv.hdr[c.recv.hdr_len:24]) 480 if n < 0 { 481 n = 0 482 } else { 483 timeout_or_data = true 484 } 485 c.Mutex.Lock() 486 if n > 0 { 487 c.X.BytesReceived += uint64(n) 488 c.X.LastDataGot = time.Now() 489 c.recv.hdr_len += n 490 } 491 if e != nil { 492 c.Mutex.Unlock() 493 c.HandleError(e) 494 return // Make sure to exit here, in case of timeout 495 } 496 if c.recv.hdr_len >= 4 && !bytes.Equal(c.recv.hdr[:4], common.Magic[:]) { 497 if c.X.Debug { 498 fmt.Printf("BadMagic from %s %s \n hdr:%s n:%d\n R: %s %d / S: %s %d\n> ", c.PeerAddr.Ip(), c.Node.Agent, 499 hex.EncodeToString(c.recv.hdr[:c.recv.hdr_len]), n, 500 c.X.LastCmdRcvd, c.X.LastBtsRcvd, c.X.LastCmdSent, c.X.LastBtsSent) 501 } 502 c.Mutex.Unlock() 503 common.CountSafe("NetBadMagic") 504 c.Ban("NetBadMagic") 505 return 506 } 507 if c.broken { 508 c.Mutex.Unlock() 509 return 510 } 511 if c.recv.hdr_len == 24 { 512 c.recv.pl_len = binary.LittleEndian.Uint32(c.recv.hdr[16:20]) 513 c.recv.cmd = strings.TrimRight(string(c.recv.hdr[4:16]), "\000") 514 c.Mutex.Unlock() 515 } else { 516 if c.recv.hdr_len > 24 { 517 // hard to belive but I saw this happening twice on Windows 518 println("ERROR: hdr_len > 24 after receiving", n, "bytes") 519 c.Mutex.Unlock() 520 common.CountSafe("SockReadOverflow") 521 c.Disconnect(true, "SockReadOverflow") 522 return 523 } 524 c.Mutex.Unlock() 525 return 526 } 527 } 528 529 if c.recv.pl_len > 0 { 530 if c.recv.dat == nil { 531 msi := maxmsgsize(c.recv.cmd) 532 if c.recv.pl_len > msi { 533 c.DoS("Big-" + c.recv.cmd) 534 return 535 } 536 c.Mutex.Lock() 537 c.recv.dat = make([]byte, c.recv.pl_len) 538 c.recv.datlen = 0 539 c.Mutex.Unlock() 540 } 541 if c.recv.datlen < c.recv.pl_len { 542 n, e = common.SockRead(c.Conn, c.recv.dat[c.recv.datlen:]) 543 if n < 0 { 544 n = 0 545 } else { 546 timeout_or_data = true 547 } 548 if n > 0 { 549 c.Mutex.Lock() 550 c.X.BytesReceived += uint64(n) 551 c.recv.datlen += uint32(n) 552 c.Mutex.Unlock() 553 if c.recv.datlen > c.recv.pl_len { 554 println(c.PeerAddr.Ip(), "is sending more of", c.recv.cmd, "then it should have", c.recv.datlen, c.recv.pl_len) 555 c.DoS("MsgSizeMismatch") 556 return 557 } 558 } 559 if e != nil { 560 c.HandleError(e) 561 return 562 } 563 if c.MutexGetBool(&c.broken) || c.recv.datlen < c.recv.pl_len { 564 return 565 } 566 } 567 } 568 569 sh := btc.Sha2Sum(c.recv.dat) 570 if !bytes.Equal(c.recv.hdr[20:24], sh[:4]) { 571 //println(c.PeerAddr.Ip(), "Msg checksum error") 572 c.DoS("MsgBadChksum") 573 return 574 } 575 576 ret = new(BCmsg) 577 ret.cmd = c.recv.cmd 578 ret.pl = c.recv.dat 579 580 c.Mutex.Lock() 581 c.recv.hdr_len = 0 582 c.recv.cmd = "" 583 c.recv.dat = nil 584 585 c.X.LastCmdRcvd = ret.cmd 586 c.X.LastBtsRcvd = uint32(len(ret.pl)) 587 588 if !common.NoCounters.Get() { 589 srcvd := "rcvd_" + ret.cmd 590 srbts := "rbts_" + ret.cmd 591 c.cntInc(srcvd) 592 c.cntAdd(srbts, uint64(len(ret.pl))) 593 c.Mutex.Unlock() 594 common.CountSafe(srcvd) 595 common.CountSafeAdd(srbts, uint64(len(ret.pl))) 596 } else { 597 c.Mutex.Unlock() 598 } 599 600 c.LastMsgTime = time.Now() 601 602 /*if c.X.Debug { 603 fmt.Println(c.ConnID, "rcvd", cmd.cmd, len(cmd.pl)) 604 }*/ 605 606 return 607 } 608 609 // Check c.X.AuthAckGot before calling this function 610 func (c *OneConnection) GetMPNow() { 611 if common.GetBool(&common.CFG.TXPool.Enabled) { 612 select { 613 case c.GetMP <- true: 614 default: 615 fmt.Println(c.ConnID, "GetMP channel full") 616 } 617 } 618 } 619 620 func (c *OneConnection) writing_thread() { 621 for !c.IsBroken() { 622 c.Mutex.Lock() // protect access to c.SendBufProd 623 624 if c.SendBufProd == c.SendBufCons { 625 c.Mutex.Unlock() 626 // wait for a new write, but time out just in case 627 select { 628 case <-c.writing_thread_push: 629 case <-time.After(10 * time.Millisecond): 630 } 631 continue 632 } 633 634 bytes_to_send := c.SendBufProd - c.SendBufCons 635 c.Mutex.Unlock() // unprotect access to c.SendBufProd 636 637 if bytes_to_send < 0 { 638 bytes_to_send += SendBufSize 639 } 640 if c.SendBufCons+bytes_to_send > SendBufSize { 641 bytes_to_send = SendBufSize - c.SendBufCons 642 } 643 644 n, e := common.SockWrite(c.Conn, c.sendBuf[c.SendBufCons:c.SendBufCons+bytes_to_send]) 645 if n > 0 { 646 c.Mutex.Lock() 647 c.X.LastSent = time.Now() 648 c.X.BytesSent += uint64(n) 649 c.SendBufCons = (c.SendBufCons + n) & SendBufMask 650 c.Mutex.Unlock() 651 } else if e != nil { 652 c.Disconnect(true, "SendErr:"+e.Error()) 653 } else if n < 0 { 654 // It comes here if we could not send a single byte because of BW limit 655 time.Sleep(10 * time.Millisecond) 656 } 657 } 658 c.writing_thread_done.Done() 659 } 660 661 func ConnectionActive(ad *peersdb.PeerAddr) (yes bool) { 662 Mutex_net.Lock() 663 _, yes = OpenCons[ad.UniqID()] 664 Mutex_net.Unlock() 665 return 666 } 667 668 // maxmsgsize returns maximum accepted payload size of a given type of message. 669 // For wider compatibility, we assume that any var_len may be up to 9 bytes. 670 func maxmsgsize(cmd string) uint32 { 671 switch cmd { 672 case "inv": 673 return 9 + 50000*36 // the spec says "max 50000 entries" 674 case "tx": 675 return 500e3 // max segwit tx size 500KB 676 case "addr": 677 return 9 + 1000*30 // max 1000 addrs 678 case "block": 679 return 4e6 // max segwit block size 4MB 680 case "getblocks": 681 return 4 + 9 + 101*32 + 32 // MAX_LOCATOR_SZ = 101 682 case "getdata": 683 return 9 + 50000*36 // core: MAX_INV_SZ = 50000 684 case "headers": 685 return 9 + 2000*89 // core: MAX_HEADERS_RESULTS = 2000 686 case "getheaders": 687 return 4 + 9 + 101*32 + 32 // MAX_LOCATOR_SZ = 101 688 case "cmpctblock": 689 return 1e6 // 1MB shall be enough 690 case "getblocktxn": 691 return 1e6 // 1MB shall be enough 692 case "blocktxn": 693 return 4e6 // all txs that can fit withing max size block 694 case "notfound": 695 return 9 + 50000*36 // same as maximum size of getdata 696 case "getmp": 697 return 9 + 8*MAX_GETMP_TXS 698 default: 699 return 1024 // Any other type of block: maximum 1KB payload limit 700 } 701 } 702 703 func NetCloseAll() { 704 sta := time.Now() 705 println("Closing network") 706 common.NetworkClosed.Set() 707 common.SetBool(&common.ListenTCP, false) 708 Mutex_net.Lock() 709 if InConsActive > 0 || OutConsActive > 0 { 710 for _, v := range OpenCons { 711 v.Disconnect(false, "CloseAll") 712 } 713 } 714 Mutex_net.Unlock() 715 time.Sleep(1e9) // give one second for WebUI requests to complete 716 // now wait for all the connections to close 717 for { 718 Mutex_net.Lock() 719 all_done := len(OpenCons) == 0 720 Mutex_net.Unlock() 721 if all_done { 722 return 723 } 724 if time.Since(sta) > 5*time.Second { 725 Mutex_net.Lock() 726 fmt.Println("Still have open connections:", InConsActive, OutConsActive, len(OpenCons), "- please report") 727 Mutex_net.Unlock() 728 break 729 } 730 time.Sleep(1e7) 731 } 732 for TCPServerStarted { 733 time.Sleep(1e7) // give one second for all the pending messages to get processed 734 } 735 } 736 737 func DropPeer(conid uint32) { 738 Mutex_net.Lock() 739 defer Mutex_net.Unlock() 740 for _, v := range OpenCons { 741 if uint32(conid) == v.ConnID { 742 if v.X.IsSpecial { 743 v.Disconnect(false, "FromUI") 744 } else { 745 v.DoS("FromUI") 746 } 747 return 748 } 749 } 750 fmt.Println("DropPeer: There is no such an active connection", conid) 751 } 752 753 // GetMP() is called from UI, to force asking the given peer for its mempool 754 func GetMP(conid uint32) { 755 Mutex_net.Lock() 756 for _, v := range OpenCons { 757 if uint32(conid) == v.ConnID { 758 Mutex_net.Unlock() 759 v.Mutex.Lock() 760 yes := v.X.AuthAckGot // don't bother if we are not authorized there 761 v.Mutex.Unlock() 762 if yes { 763 v.GetMPNow() 764 } 765 return 766 } 767 } 768 Mutex_net.Unlock() 769 fmt.Println("GetMP: There is no such an active connection", conid) 770 } 771 772 func GetMoreHeaders() { 773 Mutex_net.Lock() 774 for _, v := range OpenCons { 775 v.ReceiveHeadersNow() 776 } 777 Mutex_net.Unlock() 778 } 779 780 func BlocksToGetCnt() (res int) { 781 MutexRcv.Lock() 782 res = len(BlocksToGet) 783 MutexRcv.Unlock() 784 return 785 } 786 787 func init() { 788 rand.Read(nonce[:]) 789 }