123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- /* 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 <http://www.gnu.org/licenses/>.
- */
- #ifndef InterfaceController_H
- #define InterfaceController_H
- #include "benc/String.h"
- #include "interface/Interface.h"
- #include "wire/Headers.h"
- #include "crypto/CryptoAuth.h"
- #include "dht/dhtcore/Router.h"
- #include "dht/dhtcore/RumorMill.h"
- #include "interface/Interface.h"
- #include "memory/Allocator.h"
- #include "switch/SwitchCore.h"
- #include "net/SwitchPinger.h"
- #include "util/log/Log.h"
- #include "util/Linker.h"
- Linker_require("interface/InterfaceController.c")
- #include <stdint.h>
- #include <stdbool.h>
- enum InterfaceController_PeerState
- {
- /**
- * In state >= NEW, a valid packet has been received but it could still be a replay.
- * Or it's an outgoing connection so we don't care about authentication.
- */
- InterfaceController_PeerState_NEW = CryptoAuth_NEW,
- InterfaceController_PeerState_HANDSHAKE1 = CryptoAuth_HANDSHAKE1,
- InterfaceController_PeerState_HANDSHAKE2 = CryptoAuth_HANDSHAKE2,
- InterfaceController_PeerState_HANDSHAKE3 = CryptoAuth_HANDSHAKE3,
- /** In state == ESTABLISHED, we know the node at the other end is authentic. */
- InterfaceController_PeerState_ESTABLISHED = CryptoAuth_ESTABLISHED,
- /** If state == UNRESPONSIVE, the peer has not responded to pings in the required timeframe. */
- InterfaceController_PeerState_UNRESPONSIVE = -1,
- /** If state is UNAUTHENTICATED, the other node has not sent a single valid packet. */
- InterfaceController_PeerState_UNAUTHENTICATED = -2,
- };
- Assert_compileTime(CryptoAuth_STATE_COUNT == 5);
- static inline char* InterfaceController_stateString(enum InterfaceController_PeerState ps)
- {
- switch (ps) {
- case InterfaceController_PeerState_NEW: return "NEW";
- case InterfaceController_PeerState_HANDSHAKE1: return "HANDSHAKE1";
- case InterfaceController_PeerState_HANDSHAKE2: return "HANDSHAKE2";
- case InterfaceController_PeerState_HANDSHAKE3: return "HANDSHAKE3";
- case InterfaceController_PeerState_ESTABLISHED: return "ESTABLISHED";
- case InterfaceController_PeerState_UNRESPONSIVE: return "UNRESPONSIVE";
- case InterfaceController_PeerState_UNAUTHENTICATED: return "UNAUTHENTICATED";
- default: return "INVALID";
- }
- }
- /**
- * Stats about a peer
- */
- struct InterfaceController_peerStats
- {
- uint8_t* pubKey;
- int state;
- uint64_t timeOfLastMessage;
- uint64_t bytesOut;
- uint64_t bytesIn;
- uint64_t switchLabel;
- bool isIncomingConnection;
- String* user;
- /** Packet loss/duplication statistics. see: ReplayProtector */
- uint32_t duplicates;
- uint32_t lostPackets;
- uint32_t receivedOutOfRange;
- };
- struct InterfaceController
- {
- /** If set, this will override the default registerPeer function */
- int (* registerPeer)(struct InterfaceController* ifController,
- uint8_t herPublicKey[32],
- String* password,
- bool requireAuth,
- bool isIncomingConnection,
- struct Interface* externalInterface);
- /** If set, this will override the default getPeer function. */
- struct InterfaceController_Peer* (* getPeer)(struct InterfaceController* ifc,
- struct Interface* iface);
- };
- struct InterfaceController_Peer
- {
- /** The interface which is registered with the switch. */
- struct Interface switchIf;
- /** The internal (wrapped by CryptoAuth) interface. */
- struct Interface* cryptoAuthIf;
- /** The external (network side) interface. */
- struct Interface* external;
- /** The label for this endpoint, needed to ping the endpoint. */
- uint64_t switchLabel;
- /** Milliseconds since the epoch when the last *valid* message was received. */
- uint64_t timeOfLastMessage;
- /** Time when the last switch ping response was received from this node. */
- uint64_t timeOfLastPing;
- /** A counter to allow for 3/4 of all pings to be skipped when a node is definitely down. */
- uint32_t pingCount;
- /** The handle which can be used to look up this endpoint in the endpoint set. */
- uint32_t handle;
- /** True if we should forget about the peer if they do not respond. */
- bool isIncomingConnection;
- /**
- * If InterfaceController_PeerState_UNAUTHENTICATED, no permanent state will be kept.
- * During transition from HANDSHAKE to ESTABLISHED, a check is done for a registeration of a
- * node which is already registered in a different switch slot, if there is one and the
- * handshake completes, it will be moved.
- */
- enum InterfaceController_PeerState state;
- // traffic counters
- uint64_t bytesOut;
- uint64_t bytesIn;
- Identity
- };
- /**
- * Add a new peer.
- * Called from the network interface when it is asked to make a connection or it autoconnects.
- * If the peer which is connected to becomes unresponsive, IC will *not* remove it but will
- * set it's state to UNRESPONSIVE and it is the job of the caller to remove the peer by freeing
- * the allocator which is provided with iface.
- *
- * BEWARE: the interface allocator you provide here may be freed by this code!
- *
- * The following cases will cause the allocator to be freed:
- *
- * 1. If a peer is registered and it turns out to have the same cryptographic key as an
- * existing peer, the existing one will be freed by the IC and the new one will take it's
- * place.
- *
- * 2. If a peer which is registered as "transient" and is unresponsive for more than
- * FORGET_AFTER_MILLISECONDS milliseconds then the session will be removed.
- *
- * @param ic the interface controller.
- * @param herPublicKey the public key of the foreign node, NULL if unknown.
- * @param password the password for authenticating with the other node or NULL if unspecified.
- * @param requireAuth true if the other node must authenticate (incoming connection).
- * @param transient if true then this peer may be forgotten.
- * @param iface an interface which pipes messages to/from this peer. The peer will be
- * deregistered if this allocator is freed.
- *
- * @return 0 if all goes well.
- * InterfaceController_registerPeer_OUT_OF_SPACE if there is no space to store the peer.
- * InterfaceController_registerPeer_BAD_KEY the provided herPublicKey is not valid.
- * InterfaceController_registerPeer_INTERNAL unspecified error.
- */
- #define InterfaceController_registerPeer_INTERNAL -3
- #define InterfaceController_registerPeer_BAD_KEY -2
- #define InterfaceController_registerPeer_OUT_OF_SPACE -1
- int InterfaceController_registerPeer(struct InterfaceController* ifController,
- uint8_t herPublicKey[32],
- String* password,
- bool requireAuth,
- bool isIncomingConnection,
- struct Interface* externalInterface);
- /**
- * Disconnect a previously registered peer.
- *
- * @param ic the if controller
- * @param herPublicKey the public key of the foreign node
- * @retrun 0 if all goes well.
- * InterfaceController_disconnectPeer_NOTFOUND if no peer with herPublicKey is found.
- */
- #define InterfaceController_disconnectPeer_NOTFOUND -1
- int InterfaceController_disconnectPeer(struct InterfaceController* ifController,
- uint8_t herPublicKey[32]);
- /**
- * Populate an empty beacon with password, public key, and version.
- * Each startup, a password is generated consisting of Headers_Beacon_PASSWORD_LEN bytes.
- * If beaconing is enabled for an interface, this password is sent out in each beacon message
- * so that others can connect.
- * NOTE: Anyone can connect to any interface, even those not beaconing, using this password.
- * The public key attached to the beacon message is the public key for this node.
- *
- * @param ic the if controller
- * @param beacon an empty buffer to place the beacon information in.
- */
- void InterfaceController_populateBeacon(struct InterfaceController* ifc,
- struct Headers_Beacon* beacon);
- /** Get the IfController peer for a registered interface. */
- struct InterfaceController_Peer* InterfaceController_getPeer(struct InterfaceController* ifc,
- struct Interface* iface);
- /**
- * Get stats for the connected peers.
- *
- * @params ic the if controller
- * @params alloc the Allocator to use for the peerStats array in statsOut
- * @params statsOut pointer to the InterfaceController_peerStats array
- * @return the number of InterfaceController_peerStats in statsOut
- */
- int InterfaceController_getPeerStats(struct InterfaceController* ic,
- struct Allocator* alloc,
- struct InterfaceController_peerStats** statsOut);
- struct InterfaceController* InterfaceController_new(struct CryptoAuth* ca,
- struct SwitchCore* switchCore,
- struct Router* router,
- struct RumorMill* rumorMill,
- struct Log* logger,
- struct EventBase* eventBase,
- struct SwitchPinger* switchPinger,
- struct Random* rand,
- struct Allocator* allocator);
- #endif
|