/* 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 . */ #ifndef InterfaceController_H #define InterfaceController_H #include "benc/String.h" #include "interface/Interface.h" #include "wire/Headers.h" #include #include enum InterfaceController_PeerState { /** If state is UNAUTHENTICATED, the other node has not sent a single valid packet. */ InterfaceController_PeerState_UNAUTHENTICATED = 0, /** In state == HANDSHAKE, a valid packet has been received but it could still be a replay. */ InterfaceController_PeerState_HANDSHAKE, /** In state == ESTABLISHED, we know the node at the other end is authentic. */ InterfaceController_PeerState_ESTABLISHED, /** If state == UNRESPONSIVE, the peer has not responded to pings in the required timeframe. */ InterfaceController_PeerState_UNRESPONSIVE }; static inline char* InterfaceController_stateString(enum InterfaceController_PeerState ps) { switch (ps) { case InterfaceController_PeerState_UNAUTHENTICATED: return "UNAUTHENTICATED"; case InterfaceController_PeerState_HANDSHAKE: return "HANDSHAKE"; case InterfaceController_PeerState_ESTABLISHED: return "ESTABLISHED"; case InterfaceController_PeerState_UNRESPONSIVE: return "UNRESPONSIVE"; 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 { /** * 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 (* const registerPeer)(struct InterfaceController* ic, uint8_t herPublicKey[32], String* password, bool requireAuth, bool transient, struct Interface* iface); /** * 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 (* const disconnectPeer)(struct InterfaceController* ic, 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 (* const populateBeacon)(struct InterfaceController* ic, struct Headers_Beacon* beacon); /** Get the current state of a registered interface. */ enum InterfaceController_PeerState (* const getPeerState)(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 (* const getPeerStats)(struct InterfaceController* ic, struct Allocator* alloc, struct InterfaceController_peerStats** statsOut); }; #define InterfaceController_getPeerState(ic, iface) \ ((ic)->getPeerState(iface)) #define InterfaceController_registerPeer(ic, herPublicKey, password, requireAuth, transient, iface)\ ((ic)->registerPeer((ic), (herPublicKey), (password), (requireAuth), (transient), (iface))) #define InterfaceController_populateBeacon(ic, beacon) \ ((ic)->populateBeacon((ic), (beacon))) #endif