This file is indexed.

/usr/include/opendht/node.h is in libopendht-dev 1.6.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 *  Copyright (C) 2014-2017 Savoir-faire Linux Inc.
 *  Author(s) : Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
 *              Simon DĂ©saulniers <simon.desaulniers@savoirfairelinux.com>
 *
 *  This program is free software; you can redistribute it 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/>.
 */

#pragma once

#include "infohash.h" // includes socket structures
#include "utils.h"
#include "sockaddr.h"

#include <list>
#include <map>

namespace dht {

struct Node;
namespace net {
struct Request;
struct Socket;
struct RequestAnswer;
} /* namespace net */

using Tid = uint32_t;
using SocketCb = std::function<void(const Sp<Node>&, net::RequestAnswer&&)>;
struct Socket {
    Socket() {}
    Socket(SocketCb&& on_receive) :
        on_receive(std::move(on_receive)) {}
    SocketCb on_receive {};
};

struct Node {
    const InfoHash id;

    Node(const InfoHash& id, const SockAddr& addr, bool client=false);
    Node(const InfoHash& id, const sockaddr* sa, socklen_t salen)
        : Node(id, SockAddr(sa, salen)) {}

    InfoHash getId() const {
        return id;
    }
    const SockAddr& getAddr() const { return addr; }
    std::string getAddrStr() const {
        return addr.toString();
    }
    bool isClient() const { return is_client; }
    bool isIncoming() { return time > reply_time; }

    const time_point& getTime() const { return time; }
    const time_point& getReplyTime() const { return reply_time; }
    void setTime(const time_point& t) { time = t; }

    /**
     * Makes notice about an additionnal authentication error with this node. Up
     * to MAX_AUTH_ERRORS errors are accepted in order to let the node recover.
     * Upon this limit, the node expires.
     */
    void authError() {
        if (++auth_errors > MAX_AUTH_ERRORS)
            setExpired();
    }
    void authSuccess() { auth_errors = 0; }

    bool isExpired() const { return expired_; }
    bool isGood(time_point now) const;
    bool isPendingMessage() const;
    size_t getPendingMessageCount() const;

    bool isOld(const time_point& now) const {
        return time + NODE_EXPIRE_TIME < now;
    }
    bool isRemovable(const time_point& now) const {
        return isExpired() and isOld(now);
    }

    NodeExport exportNode() const {
        NodeExport ne;
        ne.id = id;
        ne.sslen = addr.getLength();
        std::memcpy(&ne.ss, addr.get(), ne.sslen);
        return ne;
    }
    sa_family_t getFamily() const { return addr.getFamily(); }

    void update(const SockAddr&);

    void requested(const Sp<net::Request>& req);
    void received(time_point now, const Sp<net::Request>& req);
    Sp<net::Request> getRequest(Tid tid);
    void cancelRequest(const Sp<net::Request>& req);

    void setExpired();

    /**
     * Opens a socket on which a node will be able allowed to write for further
     * additionnal updates following the response to a previous request.
     *
     * @param node  The node which will be allowed to write on this socket.
     * @param cb    The callback to execute once updates arrive on the socket.
     *
     * @return the socket.
     */
    Tid openSocket(SocketCb&& cb);

    Sp<Socket> getSocket(Tid id);

    /**
     * Closes a socket so that no further data will be red on that socket.
     *
     * @param socket  The socket to close.
     */
    void closeSocket(Tid id);

    /**
     * Resets the state of the node so it's not expired anymore.
     */
    void reset() { expired_ = false; reply_time = time_point::min(); }

    /**
     * Generates a new request id, skipping the invalid id.
     *
     * @return the new id.
     */
    Tid getNewTid() {
        ++transaction_id;
        return transaction_id ? ++transaction_id : transaction_id;
    }

    std::string toString() const;

    OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const Node& h);

    static constexpr const std::chrono::minutes NODE_GOOD_TIME {120};

    /* The time after which we consider a node to be expirable. */
    static constexpr const std::chrono::minutes NODE_EXPIRE_TIME {10};

    /* Time for a request to timeout */
    static constexpr const std::chrono::seconds MAX_RESPONSE_TIME {1};

private:
    /* Number of times we accept authentication errors from this node. */
    static const constexpr unsigned MAX_AUTH_ERRORS {3};

    SockAddr addr;
    bool is_client {false};
    time_point time {time_point::min()};            /* last time eared about */
    time_point reply_time {time_point::min()};      /* time of last correct reply received */
    unsigned auth_errors {0};
    bool expired_ {false};
    Tid transaction_id;
    using TransactionDist = std::uniform_int_distribution<decltype(transaction_id)>;

    std::map<Tid, Sp<net::Request>> requests_ {};
    std::map<Tid, Sp<Socket>> sockets_;
};

}