diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/btfrv.cpp | 13 | ||||
| -rw-r--r-- | src/btfrv.h | 13 | ||||
| -rw-r--r-- | src/net.cpp | 25 |
3 files changed, 44 insertions, 7 deletions
diff --git a/src/btfrv.cpp b/src/btfrv.cpp index 0d02ca8..63e092e 100644 --- a/src/btfrv.cpp +++ b/src/btfrv.cpp | |||
| @@ -250,11 +250,20 @@ RvSocket RvServiceRegister(const char* relay_host, unsigned short port, | |||
| 250 | hdr[0] = (unsigned char)'S'; | 250 | hdr[0] = (unsigned char)'S'; |
| 251 | memcpy(hdr + 1, my_pubkey, 32); | 251 | memcpy(hdr + 1, my_pubkey, 32); |
| 252 | if (!WriteN(s, hdr, 33)) { CLOSESOCK(s); return RV_INVALID; } | 252 | if (!WriteN(s, hdr, 33)) { CLOSESOCK(s); return RV_INVALID; } |
| 253 | unsigned char paired = 0; | 253 | // Return here: registered, not yet paired. The relay lists the service as |
| 254 | if (!ReadN(s, &paired, 1) || paired != 0x01) { CLOSESOCK(s); return RV_INVALID; } | 254 | // soon as it reads this header. The 0x01 that used to be consumed below |
| 255 | // only arrives when somebody dials us, so blocking on it made "registered" | ||
| 256 | // and "already in use" indistinguishable to the caller -- and left the node | ||
| 257 | // unable to advertise a meeting node until after it had been reached there. | ||
| 255 | return (RvSocket)s; | 258 | return (RvSocket)s; |
| 256 | } | 259 | } |
| 257 | 260 | ||
| 261 | bool RvServiceWaitPaired(RvSocket s) | ||
| 262 | { | ||
| 263 | unsigned char paired = 0; | ||
| 264 | return ReadN((SOCKET)s, &paired, 1) && paired == 0x01; | ||
| 265 | } | ||
| 266 | |||
| 258 | RvSocket RvClientConnect(const char* relay_host, unsigned short port, | 267 | RvSocket RvClientConnect(const char* relay_host, unsigned short port, |
| 259 | const unsigned char target_pubkey[32]) | 268 | const unsigned char target_pubkey[32]) |
| 260 | { | 269 | { |
diff --git a/src/btfrv.h b/src/btfrv.h index c776201..9d6756e 100644 --- a/src/btfrv.h +++ b/src/btfrv.h | |||
| @@ -37,11 +37,20 @@ bool RvRelayRun(unsigned short port); | |||
| 37 | void RvRelayStop(); | 37 | void RvRelayStop(); |
| 38 | 38 | ||
| 39 | // ---- service side (the node being reached by its .btf address) ---- | 39 | // ---- service side (the node being reached by its .btf address) ---- |
| 40 | // Register at the relay under `my_pubkey` (32 bytes) and block until a client is | 40 | // Register at the relay under `my_pubkey` (32 bytes). Returns as soon as the |
| 41 | // paired to us. Returns the paired socket, or RV_INVALID on error. | 41 | // relay has us listed, WITHOUT waiting for anyone to dial -- the caller needs |
| 42 | // that moment to start advertising this relay as its meeting node. Waiting for | ||
| 43 | // the dial was folded into this call before, which deadlocked discovery: a node | ||
| 44 | // could not be advertised until it had been dialled, and could not be dialled | ||
| 45 | // until it was advertised. Returns RV_INVALID on error. | ||
| 42 | RvSocket RvServiceRegister(const char* relay_host, unsigned short port, | 46 | RvSocket RvServiceRegister(const char* relay_host, unsigned short port, |
| 43 | const unsigned char my_pubkey[32]); | 47 | const unsigned char my_pubkey[32]); |
| 44 | 48 | ||
| 49 | // Block on a registered service socket until a client is paired to us. Returns | ||
| 50 | // false if the relay drops us or errors, in which case the caller should close | ||
| 51 | // the socket and register again. | ||
| 52 | bool RvServiceWaitPaired(RvSocket s); | ||
| 53 | |||
| 45 | // ---- client side (the node dialing a .btf address) ---- | 54 | // ---- client side (the node dialing a .btf address) ---- |
| 46 | // Connect through the relay to the service registered under `target_pubkey`. | 55 | // Connect through the relay to the service registered under `target_pubkey`. |
| 47 | // Returns the paired socket, or RV_INVALID on error. | 56 | // Returns the paired socket, or RV_INVALID on error. |
diff --git a/src/net.cpp b/src/net.cpp index 7b2ef83..b5d12d0 100644 --- a/src/net.cpp +++ b/src/net.cpp | |||
| @@ -554,7 +554,10 @@ void ThreadBtfAccept(void* parg) | |||
| 554 | string strHost = strMeeting.substr(0, colon); | 554 | string strHost = strMeeting.substr(0, colon); |
| 555 | int nPort = atoi(strMeeting.substr(colon + 1).c_str()); | 555 | int nPort = atoi(strMeeting.substr(colon + 1).c_str()); |
| 556 | 556 | ||
| 557 | // Blocks until a client is paired to us (or the relay drops us) | 557 | // Returns as soon as the relay has us listed -- it does not wait for a |
| 558 | // dial. That distinction is the whole point: we have to be advertised | ||
| 559 | // before anyone can dial us, so registering and waiting cannot be the | ||
| 560 | // same call. | ||
| 558 | btf::RvSocket rv = btf::RvServiceRegister(strHost.c_str(), (unsigned short)nPort, pk); | 561 | btf::RvSocket rv = btf::RvServiceRegister(strHost.c_str(), (unsigned short)nPort, pk); |
| 559 | if (fShutdown) | 562 | if (fShutdown) |
| 560 | { | 563 | { |
| @@ -564,13 +567,29 @@ void ThreadBtfAccept(void* parg) | |||
| 564 | } | 567 | } |
| 565 | if (rv == btf::RV_INVALID) | 568 | if (rv == btf::RV_INVALID) |
| 566 | { | 569 | { |
| 570 | LogPrint("net", "rendezvous: could not register at %s, trying another\n", | ||
| 571 | strMeeting.c_str()); | ||
| 567 | iRelay++; // this relay is down/attacked -> try the next one | 572 | iRelay++; // this relay is down/attacked -> try the next one |
| 568 | Sleep(3000); | 573 | Sleep(3000); |
| 569 | continue; | 574 | continue; |
| 570 | } | 575 | } |
| 571 | // Registered OK: advertise THIS relay in our descriptor so clients dial | 576 | |
| 572 | // us here, and keep using it (iRelay unchanged) until it fails. | 577 | // Registered. Advertise THIS relay now, while we are listed and before |
| 578 | // anybody dials -- a descriptor naming it is what makes a dial possible | ||
| 579 | // at all. Keep using it (iRelay unchanged) until it fails. | ||
| 573 | BtfSetActiveRelay(strMeeting); | 580 | BtfSetActiveRelay(strMeeting); |
| 581 | LogPrint("net", "rendezvous: registered at %s, waiting for a dial\n", | ||
| 582 | strMeeting.c_str()); | ||
| 583 | |||
| 584 | // Now block for someone to arrive. | ||
| 585 | if (!btf::RvServiceWaitPaired(rv)) | ||
| 586 | { | ||
| 587 | btf::RvClose(rv); | ||
| 588 | LogPrint("net", "rendezvous: %s dropped us before any dial, re-registering\n", | ||
| 589 | strMeeting.c_str()); | ||
| 590 | continue; | ||
| 591 | } | ||
| 592 | |||
| 574 | btf_socket_t hSocket = btf::BtfServiceWrap(rv, sk); | 593 | btf_socket_t hSocket = btf::BtfServiceWrap(rv, sk); |
| 575 | if (hSocket == INVALID_SOCKET) | 594 | if (hSocket == INVALID_SOCKET) |
| 576 | continue; | 595 | continue; |