/** * @file lltransfermanager.h * @brief Improved transfer mechanism for moving data through the * message system. * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library 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; * version 2.1 of the License only. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LL_LLTRANSFERMANAGER_H #define LL_LLTRANSFERMANAGER_H #include <map> #include <list> #include "llhost.h" #include "lluuid.h" #include "llthrottle.h" #include "llpriqueuemap.h" #include "llassettype.h" // // Definition of the manager class for the new LLXfer replacement. // Provides prioritized, bandwidth-throttled transport of arbitrary // binary data between host/circuit combos // typedef enum e_transfer_channel_type { LLTCT_UNKNOWN = 0, LLTCT_MISC, LLTCT_ASSET, LLTCT_NUM_TYPES } LLTransferChannelType; typedef enum e_transfer_source_type { LLTST_UNKNOWN = 0, LLTST_FILE, LLTST_ASSET, LLTST_SIM_INV_ITEM, // Simulator specific, may not be handled LLTST_SIM_ESTATE, // Simulator specific, may not be handled LLTST_NUM_TYPES } LLTransferSourceType; typedef enum e_transfer_target_type { LLTTT_UNKNOWN = 0, LLTTT_FILE, LLTTT_VFILE, LLTTT_NUM_TYPES } LLTransferTargetType; // Errors are negative, expected values are positive. typedef enum e_status_codes { LLTS_OK = 0, LLTS_DONE = 1, LLTS_SKIP = 2, LLTS_ABORT = 3, LLTS_ERROR = -1, LLTS_UNKNOWN_SOURCE = -2, // Equivalent of a 404 LLTS_INSUFFICIENT_PERMISSIONS = -3 // Not enough permissions } LLTSCode; // Types of requests for estate wide information typedef enum e_estate_type { ET_Covenant = 0, ET_NONE = -1 } EstateAssetType; class LLMessageSystem; class LLDataPacker; class LLTransferConnection; class LLTransferSourceChannel; class LLTransferTargetChannel; class LLTransferSourceParams; class LLTransferTargetParams; class LLTransferSource; class LLTransferTarget; class LLTransferManager { public: LLTransferManager(); virtual ~LLTransferManager(); void init(); void cleanup(); void updateTransfers(); // Called per frame to push packets out on the various different channels. void cleanupConnection(const LLHost &host); LLTransferSourceChannel *getSourceChannel(const LLHost &host, const LLTransferChannelType stype); LLTransferTargetChannel *getTargetChannel(const LLHost &host, const LLTransferChannelType stype); LLTransferSource *findTransferSource(const LLUUID &transfer_id); BOOL isValid() const { return mValid; } static void processTransferRequest(LLMessageSystem *mesgsys, void **); static void processTransferInfo(LLMessageSystem *mesgsys, void **); static void processTransferPacket(LLMessageSystem *mesgsys, void **); static void processTransferAbort(LLMessageSystem *mesgsys, void **); static void reliablePacketCallback(void **, S32 result); S32 getTransferBitsIn(const LLTransferChannelType tctype) const { return mTransferBitsIn[tctype]; } S32 getTransferBitsOut(const LLTransferChannelType tctype) const { return mTransferBitsOut[tctype]; } void resetTransferBitsIn(const LLTransferChannelType tctype) { mTransferBitsIn[tctype] = 0; } void resetTransferBitsOut(const LLTransferChannelType tctype) { mTransferBitsOut[tctype] = 0; } void addTransferBitsIn(const LLTransferChannelType tctype, const S32 bits) { mTransferBitsIn[tctype] += bits; } void addTransferBitsOut(const LLTransferChannelType tctype, const S32 bits) { mTransferBitsOut[tctype] += bits; } protected: LLTransferConnection *getTransferConnection(const LLHost &host); BOOL removeTransferConnection(const LLHost &host); protected: // Convenient typedefs typedef std::map<LLHost, LLTransferConnection *> host_tc_map; BOOL mValid; LLHost mHost; S32 mTransferBitsIn[LLTTT_NUM_TYPES]; S32 mTransferBitsOut[LLTTT_NUM_TYPES]; // We keep a map between each host and LLTransferConnection. host_tc_map mTransferConnections; }; // // Keeps tracks of all channels to/from a particular host. // class LLTransferConnection { public: LLTransferConnection(const LLHost &host); virtual ~LLTransferConnection(); void updateTransfers(); LLTransferSourceChannel *getSourceChannel(const LLTransferChannelType type); LLTransferTargetChannel *getTargetChannel(const LLTransferChannelType type); // Convenient typedefs typedef std::list<LLTransferSourceChannel *>::iterator tsc_iter; typedef std::list<LLTransferTargetChannel *>::iterator ttc_iter; friend class LLTransferManager; protected: LLHost mHost; std::list<LLTransferSourceChannel *> mTransferSourceChannels; std::list<LLTransferTargetChannel *> mTransferTargetChannels; }; // // A channel which is pushing data out. // class LLTransferSourceChannel { public: LLTransferSourceChannel(const LLTransferChannelType channel_type, const LLHost &host); virtual ~LLTransferSourceChannel(); void updateTransfers(); void updatePriority(LLTransferSource *tsp, const F32 priority); void addTransferSource(LLTransferSource *sourcep); LLTransferSource *findTransferSource(const LLUUID &transfer_id); void deleteTransfer(LLTransferSource *tsp); void setThrottleID(const S32 throttle_id) { mThrottleID = throttle_id; } LLTransferChannelType getChannelType() const { return mChannelType; } LLHost getHost() const { return mHost; } protected: typedef std::list<LLTransferSource *>::iterator ts_iter; LLTransferChannelType mChannelType; LLHost mHost; LLPriQueueMap<LLTransferSource*> mTransferSources; // The throttle that this source channel should use S32 mThrottleID; }; // // A channel receiving data from a source. // class LLTransferTargetChannel { public: LLTransferTargetChannel(const LLTransferChannelType channel_type, const LLHost &host); virtual ~LLTransferTargetChannel(); void requestTransfer(const LLTransferSourceParams &source_params, const LLTransferTargetParams &target_params, const F32 priority); LLTransferTarget *findTransferTarget(const LLUUID &transfer_id); void deleteTransfer(LLTransferTarget *ttp); LLTransferChannelType getChannelType() const { return mChannelType; } LLHost getHost() const { return mHost; } protected: void sendTransferRequest(LLTransferTarget *targetp, const LLTransferSourceParams ¶ms, const F32 priority); void addTransferTarget(LLTransferTarget *targetp); friend class LLTransferTarget; friend class LLTransferManager; protected: typedef std::list<LLTransferTarget *>::iterator tt_iter; LLTransferChannelType mChannelType; LLHost mHost; std::list<LLTransferTarget *> mTransferTargets; }; class LLTransferSourceParams { public: LLTransferSourceParams(const LLTransferSourceType type) : mType(type) { } virtual ~LLTransferSourceParams(); virtual void packParams(LLDataPacker &dp) const = 0; virtual BOOL unpackParams(LLDataPacker &dp) = 0; LLTransferSourceType getType() const { return mType; } protected: LLTransferSourceType mType; }; // // LLTransferSource is an interface, all transfer sources should be derived from it. // typedef LLTransferSource *(*LLTransferSourceCreateFunc)(const LLUUID &id, const F32 priority); class LLTransferSource { public: LLUUID getID() { return mID; } friend class LLTransferManager; friend class LLTransferSourceChannel; protected: LLTransferSource(const LLTransferSourceType source_type, const LLUUID &request_id, const F32 priority); virtual ~LLTransferSource(); void sendTransferStatus(LLTSCode status); // When you've figured out your transfer status, do this virtual void initTransfer() = 0; virtual F32 updatePriority() = 0; virtual LLTSCode dataCallback(const S32 packet_id, const S32 max_bytes, U8 **datap, S32 &returned_bytes, BOOL &delete_returned) = 0; // The completionCallback is GUARANTEED to be called before the destructor. virtual void completionCallback(const LLTSCode status) = 0; virtual void packParams(LLDataPacker& dp) const = 0; virtual BOOL unpackParams(LLDataPacker& dp) = 0; virtual S32 getNextPacketID() { return mLastPacketID + 1; } virtual void setLastPacketID(const S32 packet_id) { mLastPacketID = packet_id; } // For now, no self-induced priority changes F32 getPriority() { return mPriority; } void setPriority(const F32 pri) { mPriority = pri; } virtual void abortTransfer(); // DON'T USE THIS ONE, used internally by LLTransferManager static LLTransferSource *createSource(const LLTransferSourceType stype, const LLUUID &request_id, const F32 priority); static void registerSourceType(const LLTransferSourceType stype, LLTransferSourceCreateFunc); static void sSetPriority(LLTransferSource *&tsp, const F32 priority); static F32 sGetPriority(LLTransferSource *&tsp); protected: typedef std::map<LLTransferSourceType, LLTransferSourceCreateFunc> stype_scfunc_map; static stype_scfunc_map sSourceCreateMap; LLTransferSourceType mType; LLUUID mID; LLTransferSourceChannel *mChannelp; F32 mPriority; S32 mSize; S32 mLastPacketID; }; class LLTransferTargetParams { public: LLTransferTargetParams(const LLTransferTargetType type) : mType(type) {} LLTransferTargetType getType() const { return mType; } protected: LLTransferTargetType mType; }; class LLTransferPacket { // Used for storing a packet that's being delivered later because it's out of order. // ONLY should be accessed by the following two classes, for now. friend class LLTransferTarget; friend class LLTransferManager; protected: LLTransferPacket(const S32 packet_id, const LLTSCode status, const U8 *datap, const S32 size); virtual ~LLTransferPacket(); protected: S32 mPacketID; LLTSCode mStatus; U8 *mDatap; S32 mSize; }; class LLTransferTarget { public: LLTransferTarget( LLTransferTargetType target_type, const LLUUID& transfer_id, LLTransferSourceType source_type); virtual ~LLTransferTarget(); // Accessors LLUUID getID() const { return mID; } LLTransferTargetType getType() const { return mType; } LLTransferTargetChannel *getChannel() const { return mChannelp; } LLTransferSourceType getSourceType() const { return mSourceType; } // Static functionality static LLTransferTarget* createTarget( LLTransferTargetType target_type, const LLUUID& request_id, LLTransferSourceType source_type); // friends friend class LLTransferManager; friend class LLTransferTargetChannel; protected: // Implementation virtual bool unpackParams(LLDataPacker& dp) = 0; virtual void applyParams(const LLTransferTargetParams ¶ms) = 0; virtual LLTSCode dataCallback(const S32 packet_id, U8 *in_datap, const S32 in_size) = 0; // The completionCallback is GUARANTEED to be called before the destructor, so all handling // of errors/aborts should be done here. virtual void completionCallback(const LLTSCode status) = 0; void abortTransfer(); virtual S32 getNextPacketID() { return mLastPacketID + 1; } virtual void setLastPacketID(const S32 packet_id) { mLastPacketID = packet_id; } void setSize(const S32 size) { mSize = size; } void setGotInfo(const BOOL got_info) { mGotInfo = got_info; } BOOL gotInfo() const { return mGotInfo; } bool addDelayedPacket( const S32 packet_id, const LLTSCode status, U8* datap, const S32 size); protected: typedef std::map<S32, LLTransferPacket *> transfer_packet_map; typedef std::map<S32, LLTransferPacket *>::iterator tpm_iter; LLTransferTargetType mType; LLTransferSourceType mSourceType; LLUUID mID; LLTransferTargetChannel *mChannelp; BOOL mGotInfo; S32 mSize; S32 mLastPacketID; transfer_packet_map mDelayedPacketMap; // Packets that are waiting because of missing/out of order issues }; // Hack, here so it's publicly available even though LLTransferSourceInvItem is only available on the simulator class LLTransferSourceParamsInvItem: public LLTransferSourceParams { public: LLTransferSourceParamsInvItem(); virtual ~LLTransferSourceParamsInvItem() {} /*virtual*/ void packParams(LLDataPacker &dp) const; /*virtual*/ BOOL unpackParams(LLDataPacker &dp); void setAgentSession(const LLUUID &agent_id, const LLUUID &session_id); void setInvItem(const LLUUID &owner_id, const LLUUID &task_id, const LLUUID &item_id); void setAsset(const LLUUID &asset_id, const LLAssetType::EType at); LLUUID getAgentID() const { return mAgentID; } LLUUID getSessionID() const { return mSessionID; } LLUUID getOwnerID() const { return mOwnerID; } LLUUID getTaskID() const { return mTaskID; } LLUUID getItemID() const { return mItemID; } LLUUID getAssetID() const { return mAssetID; } LLAssetType::EType getAssetType() const { return mAssetType; } protected: LLUUID mAgentID; LLUUID mSessionID; LLUUID mOwnerID; LLUUID mTaskID; LLUUID mItemID; LLUUID mAssetID; LLAssetType::EType mAssetType; }; // Hack, here so it's publicly available even though LLTransferSourceEstate is only available on the simulator class LLTransferSourceParamsEstate: public LLTransferSourceParams { public: LLTransferSourceParamsEstate(); virtual ~LLTransferSourceParamsEstate() {} /*virtual*/ void packParams(LLDataPacker &dp) const; /*virtual*/ BOOL unpackParams(LLDataPacker &dp); void setAgentSession(const LLUUID &agent_id, const LLUUID &session_id); void setEstateAssetType(const EstateAssetType etype); void setAsset(const LLUUID &asset_id, const LLAssetType::EType at); LLUUID getAgentID() const { return mAgentID; } LLUUID getSessionID() const { return mSessionID; } EstateAssetType getEstateAssetType() const { return mEstateAssetType; } LLUUID getAssetID() const { return mAssetID; } LLAssetType::EType getAssetType() const { return mAssetType; } protected: LLUUID mAgentID; LLUUID mSessionID; EstateAssetType mEstateAssetType; // these are set on the sim based on estateinfotype LLUUID mAssetID; LLAssetType::EType mAssetType; }; extern LLTransferManager gTransferManager; #endif//LL_LLTRANSFERMANAGER_H