123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- /* vim: set expandtab ts=4 sw=4: */
- /*
- * You may redistribute this program and/or modify it under the terms of
- * the GNU General Public License as published by the Free Software Foundation,
- * either version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include "subnode/GetPeersResponder.h"
- #include "subnode/BoilerplateResponder.h"
- #include "dht/dhtcore/ReplySerializer.h"
- #include "util/Identity.h"
- #define GETPEERS_RESPONSE_NODES 8
- struct GetPeersResponder_pvt
- {
- struct GetPeersResponder pub;
- struct MsgCore_Handler* handler;
- struct AddrSet* peers;
- struct Log* log;
- struct Allocator* alloc;
- struct MsgCore* msgCore;
- struct Address* selfAddr;
- struct BoilerplateResponder* br;
- struct EncodingScheme* myScheme;
- Identity
- };
- static void onGetPeers(Dict* msg,
- struct Address* src,
- struct Allocator* tmpAlloc,
- struct MsgCore_Handler* handler)
- {
- struct GetPeersResponder_pvt* gprp =
- Identity_check((struct GetPeersResponder_pvt*) handler->userData);
- Log_debug(gprp->log, "Received getPeers req from [%s]", Address_toString(src, tmpAlloc)->bytes);
- String* txid = Dict_getStringC(msg, "txid");
- if (!txid) {
- Log_debug(gprp->log, "getPeers missing txid");
- return;
- }
- String* nearLabelStr = Dict_getStringC(msg, "tar");
- uint64_t label;
- if (!nearLabelStr || nearLabelStr->len != 8) {
- Log_debug(gprp->log, "getPeers does not contain proper target");
- return;
- } else {
- uint64_t label_be;
- Bits_memcpy(&label_be, nearLabelStr->bytes, 8);
- label = Endian_bigEndianToHost64(label_be);
- }
- struct Address** ptrList =
- Allocator_calloc(tmpAlloc, sizeof(uintptr_t), GETPEERS_RESPONSE_NODES+1);
- ptrList[GETPEERS_RESPONSE_NODES-1] = gprp->selfAddr;
- if (label > 1) {
- int formNum = EncodingScheme_getFormNum(gprp->myScheme, label);
- if (formNum > -1) {
- int bitsUsed = EncodingScheme_formSize(&gprp->myScheme->forms[formNum]);
- label = (label & Bits_maxBits64(bitsUsed)) | 1 << bitsUsed;
- }
- }
- for (int i = 0; i < gprp->peers->length; i++) {
- struct Address* peer = AddrSet_get(gprp->peers, i);
- if (peer->path < label) { continue; }
- int j;
- for (j = 0; j < GETPEERS_RESPONSE_NODES; j++) {
- if (!ptrList[j]) { continue; }
- if ((ptrList[j]->path - label) > (peer->path - label)) { continue; }
- break;
- }
- switch (j) {
- default: Bits_memmove(ptrList, &ptrList[1], (j - 1) * sizeof(char*));
- Gcc_FALLTHRU;
- case 1: ptrList[j - 1] = peer;
- Gcc_FALLTHRU;
- case 0:;
- }
- }
- Assert_true(!ptrList[GETPEERS_RESPONSE_NODES]);
- struct Address* addrList =
- Allocator_calloc(tmpAlloc, sizeof(struct Address), GETPEERS_RESPONSE_NODES+1);
- int size = 0;
- for (int i = 0; i < GETPEERS_RESPONSE_NODES; i++) {
- if (!ptrList[i]) { continue; }
- Bits_memcpy(&addrList[size++], ptrList[i], sizeof(struct Address));
- }
- Assert_true(Bits_isZero(&addrList[GETPEERS_RESPONSE_NODES], sizeof(struct Address)));
- Dict* responseDict = Dict_new(tmpAlloc);
- ReplySerializer_serialize((&(struct Address_List) { .elems = addrList, .length = size }),
- responseDict,
- src,
- tmpAlloc);
- Dict_putStringC(responseDict, "txid", txid, tmpAlloc);
- BoilerplateResponder_addBoilerplate(gprp->br, responseDict, src, tmpAlloc);
- MsgCore_sendResponse(gprp->msgCore, responseDict, src, tmpAlloc);
- }
- struct GetPeersResponder* GetPeersResponder_new(struct Allocator* allocator,
- struct Log* log,
- struct AddrSet* peers,
- struct Address* selfAddr,
- struct MsgCore* msgCore,
- struct BoilerplateResponder* br,
- struct EncodingScheme* myScheme)
- {
- struct Allocator* alloc = Allocator_child(allocator);
- struct GetPeersResponder_pvt* gprp =
- Allocator_calloc(alloc, sizeof(struct GetPeersResponder_pvt), 1);
- Identity_set(gprp);
- gprp->peers = peers;
- gprp->log = log;
- gprp->alloc = alloc;
- gprp->msgCore = msgCore;
- gprp->selfAddr = selfAddr;
- gprp->handler = MsgCore_onQuery(msgCore, "gp", alloc);
- gprp->handler->userData = gprp;
- gprp->handler->cb = onGetPeers;
- gprp->br = br;
- gprp->myScheme = myScheme;
- return &gprp->pub;
- }
|