/******************************************************************************* * libretroshare/src/tcponudp: udprelay.h * * * * libretroshare: retroshare core library * * * * Copyright 2010-2010 by Robert Fernie * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public License * * along with this program. If not, see . * * * *******************************************************************************/ #ifndef RS_UDP_RELAY_H #define RS_UDP_RELAY_H #include "tcponudp/udppeer.h" #include #include class UdpRelayAddrSet; class UdpRelayAddrSet { public: UdpRelayAddrSet(); UdpRelayAddrSet(const sockaddr_in *ownAddr, const sockaddr_in *destAddr); UdpRelayAddrSet flippedSet(); struct sockaddr_in mSrcAddr; /* msg source */ struct sockaddr_in mDestAddr; /* final destination */ }; int operator<(const UdpRelayAddrSet &a, const UdpRelayAddrSet &b); class UdpRelayProxy { public: UdpRelayProxy(); UdpRelayProxy(UdpRelayAddrSet *addrSet, int relayClass, uint32_t bandwidth); UdpRelayAddrSet mAddrs; double mBandwidth; uint32_t mDataSize; rstime_t mLastBandwidthTS; rstime_t mLastTS; rstime_t mStartTS; double mBandwidthLimit; int mRelayClass; }; class UdpRelayEnd { public: UdpRelayEnd(); UdpRelayEnd(UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); struct sockaddr_in mLocalAddr; struct sockaddr_in mProxyAddr; struct sockaddr_in mRemoteAddr; }; std::ostream &operator<<(std::ostream &out, const UdpRelayAddrSet &uras); std::ostream &operator<<(std::ostream &out, const UdpRelayProxy &urp); std::ostream &operator<<(std::ostream &out, const UdpRelayEnd &ure); /* we define a couple of classes (determining which class is done elsewhere) * There will be various maximums for each type. * Ideally you want to allow your friends to use your proxy in preference * to randoms. * * At N x 2 x maxBandwidth. * * 10 x 2 x 1Kb/s => 20Kb/s In and Out. (quite a bit!) * 20 x 2 x 1Kb/s => 40Kb/s Huge. */ #define UDP_RELAY_DEFAULT_COUNT_ALL 2 #define UDP_RELAY_DEFAULT_FRIEND 0 #define UDP_RELAY_DEFAULT_FOF 1 #define UDP_RELAY_DEFAULT_GENERAL 1 #define UDP_RELAY_DEFAULT_BANDWIDTH 1024 #define UDP_RELAY_FRAC_GENERAL (0.5) #define UDP_RELAY_FRAC_FOF (0.5) #define UDP_RELAY_FRAC_FRIENDS (0.0) /**** DEFINED IN EXTERNAL HEADER FILE ***/ // sehraf: this is a bit ugly but since the int is used as an integer i'lll stick to this hack for now /// TODO fix me! #define UDP_RELAY_NUM_CLASS static_cast::type>(RsDhtRelayClass::NUM_CLASS) #define UDP_RELAY_CLASS_ALL static_cast::type>(RsDhtRelayClass::ALL) #define UDP_RELAY_CLASS_GENERAL static_cast::type>(RsDhtRelayClass::GENERAL) #define UDP_RELAY_CLASS_FOF static_cast::type>(RsDhtRelayClass::FOF) #define UDP_RELAY_CLASS_FRIENDS static_cast::type>(RsDhtRelayClass::FRIENDS) // Just for some testing fun! //#define UDP_RELAY_LIFETIME_GENERAL 180 // 3 minutes //#define UDP_RELAY_LIFETIME_FOF 360 // 6 minutes. //#define UDP_RELAY_LIFETIME_FRIENDS 720 // 12 minutes. #define UDP_RELAY_LIFETIME_GENERAL 3600 // 1 hour (chosen so we at least transfer 1 or 2 meg at lowest speed) #define UDP_RELAY_LIFETIME_FOF 7200 // 2 Hours. #define UDP_RELAY_LIFETIME_FRIENDS 14400 // 4 Hours. #define STD_RELAY_TTL 64 class UdpRelayReceiver: public UdpSubReceiver { public: UdpRelayReceiver(UdpPublisher *pub); virtual ~UdpRelayReceiver(); /* add a TCPonUDP stream (ENDs) */ int addUdpPeer(UdpPeer *peer, UdpRelayAddrSet *endPoints, const struct sockaddr_in *proxyaddr); int removeUdpPeer(UdpPeer *peer); /* add a Relay Point (for the Relay). * These don't have to be explicitly removed. * They will be timed out when * the end-points drop the connections */ int addUdpRelay(UdpRelayAddrSet *addrSet, int &relayClass, uint32_t &bandwidth); int removeUdpRelay(UdpRelayAddrSet *addrs); /* Need some stats, to work out how many relays we are supporting */ int checkRelays(); int setRelayTotal(int count); /* sets all the Relay Counts (frac based on total) */ int setRelayClassMax(int classIdx, int count, int bandwidth); /* set a specific class maximum */ int getRelayClassMax(int classIdx); int getRelayClassBandwidth(int classIdx); int getRelayCount(int classIdx); /* how many relays (of this type) do we have */ int RelayStatus(std::ostream &out); /* Extract Relay Data */ int getRelayEnds(std::list &relayEnds); int getRelayProxies(std::list &relayProxies); /* callback for recved data (overloaded from UdpReceiver) */ virtual int recvPkt(void *data, int size, struct sockaddr_in &from); /* wrapper function for relay (overloaded from UdpSubReceiver) */ virtual int sendPkt(const void *data, int size, const struct sockaddr_in &to, int ttl); int status(std::ostream &out); int UdpPeersStatus(std::ostream &out); void getDataTransferred(uint32_t &read, uint32_t &write, uint32_t &relay); private: void clearDataTransferred(); int removeUdpRelay_relayLocked(UdpRelayAddrSet *addrs); int installRelayClass_relayLocked(int &classIdx, uint32_t &bandwidth); int removeRelayClass_relayLocked(int classIdx); /* Unfortunately, Due the reentrant nature of this classes activities... * the SendPkt() must be callable from inside RecvPkt(). * This means we need two seperate mutexes. * - one for UdpPeer's, and one for Relay Data. * * care must be taken to lock these mutex's in a consistent manner to avoid deadlock. * - You are not allowed to hold both at the same time! */ RsMutex udppeerMtx; /* for all class data (below) */ std::map mPeers; /* indexed by */ uint32_t mReadBytes; RsMutex relayMtx; /* for all class data (below) */ std::vector mClassLimit, mClassCount, mClassBandwidth; std::map mStreams; /* indexed by */ std::map mRelays; /* indexed by */ void *mTmpSendPkt; uint32_t mTmpSendSize; uint32_t mWriteBytes; uint32_t mRelayBytes; }; /* utility functions for creating / extracting UdpRelayPackets */ int isUdpRelayPacket(const void *data, const int size); int getPacketFromUdpRelayPacket(const void *data, const int size, void **realdata, int *realsize); int createRelayUdpPacket(const void *data, const int size, void *newpkt, int newsize, UdpRelayEnd *ure); int extractUdpRelayAddrSet(const void *data, const int size, UdpRelayAddrSet &addrSet); #endif