diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 9d35f1dda..5be74c036 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -343,3 +343,41 @@ bool LLAssetType::lookupIsLinkType(EType asset_type) { return (asset_type == AT_LINK || asset_type == AT_LINK_FOLDER); } + +// static +bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type) +{ + // *FIX: Make this list smaller. + switch(asset_type) + { + case LLAssetType::AT_SOUND: + case LLAssetType::AT_LANDMARK: + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_ANIMATION: + case LLAssetType::AT_GESTURE: + return true; + } + return false; +} + +// static +bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) +{ + switch(asset_type) + { + case LLAssetType::AT_TEXTURE: + case LLAssetType::AT_SOUND: + case LLAssetType::AT_LANDMARK: + case LLAssetType::AT_CLOTHING: + case LLAssetType::AT_NOTECARD: + case LLAssetType::AT_BODYPART: + case LLAssetType::AT_ANIMATION: + case LLAssetType::AT_GESTURE: + case LLAssetType::AT_LINK: + case LLAssetType::AT_LINK_FOLDER: + return true; + } + return false; +} + diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 83bf8b629..a769e165c 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -30,8 +30,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLASSETTYPE -#define LL_LLASSETTYPE +#ifndef LL_LLASSETTYPE_H +#define LL_LLASSETTYPE_H #include @@ -179,9 +179,12 @@ public: static EType getType(const std::string& sin); static std::string getDesc(EType type); - static bool lookupCanLink(EType asset_type); - static bool lookupIsLinkType(EType asset_type); + static bool lookupCanLink(EType asset_type); + static bool lookupIsLinkType(EType asset_type); + static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download + static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer + private: // don't instantiate or derive one of these objects LLAssetType( void ) {} diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h index 6517b7017..867d6bdbf 100644 --- a/indra/llcommon/llavatarconstants.h +++ b/indra/llcommon/llavatarconstants.h @@ -52,10 +52,10 @@ const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used p const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known. const U32 AVATAR_AGEVERIFIED = 0x1 << 5; // whether avatar has been age-verified -static const std::string VISIBILITY_DEFAULT("default"); -static const std::string VISIBILITY_HIDDEN("hidden"); -static const std::string VISIBILITY_VISIBLE("visible"); -static const std::string VISIBILITY_INVISIBLE("invisible"); +char const* const VISIBILITY_DEFAULT = "default"; +char const* const VISIBILITY_HIDDEN = "hidden"; +char const* const VISIBILITY_VISIBLE = "visible"; +char const* const VISIBILITY_INVISIBLE = "invisible"; #endif diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 4c35cee57..c68c000fa 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -290,7 +290,7 @@ namespace public: static LogControlFile& fromDirectory(const std::string& dir); - virtual void loadFile(); + virtual bool loadFile(); private: LogControlFile(const std::string &filename) @@ -318,7 +318,7 @@ namespace // NB: This instance is never freed } - void LogControlFile::loadFile() + bool LogControlFile::loadFile() { LLSD configuration; @@ -334,12 +334,13 @@ namespace llwarns << filename() << " missing, ill-formed," " or simply undefined; not changing configuration" << llendl; - return; + return false; } } LLError::configure(configuration); llinfos << "logging reconfigured from " << filename() << llendl; + return true; } @@ -601,12 +602,18 @@ namespace LLError s.printLocation = print; } - void setFatalFunction(FatalFunction f) + void setFatalFunction(const FatalFunction& f) { Settings& s = Settings::get(); s.crashFunction = f; } + FatalFunction getFatalFunction() + { + Settings& s = Settings::get(); + return s.crashFunction; + } + void setTimeFunction(TimeFunction f) { Settings& s = Settings::get(); @@ -1211,14 +1218,17 @@ namespace LLError void crashAndLoop(const std::string& message) { // Now, we go kaboom! - int* crash = NULL; + int* make_me_crash = NULL; - *crash = 0; + *make_me_crash = 0; while(true) { // Loop forever, in case the crash didn't work? } + + // this is an attempt to let Coverity and other semantic scanners know that this function won't be returning ever. + exit(EXIT_FAILURE); } #if LL_WINDOWS #pragma optimize("", on) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 0e770d461..f841637b3 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -242,7 +242,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG; do { \ static LLError::CallSite _site( \ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\ - if (_site.shouldLog()) \ + if (LL_UNLIKELY(_site.shouldLog())) \ { \ std::ostringstream* _out = LLError::Log::out(); \ (*_out) diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index cde072209..2a7c500db 100644 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -35,7 +35,7 @@ #define LL_LLERRORCONTROL_H #include "llerror.h" - +#include "boost/function.hpp" #include class LLSD; @@ -95,16 +95,37 @@ namespace LLError Control functions. */ - typedef void(*FatalFunction)(const std::string& message); + typedef boost::function FatalFunction; LL_COMMON_API void crashAndLoop(const std::string& message); - // Default fatal funtion: access null pointer and loops forever + // Default fatal function: access null pointer and loops forever - LL_COMMON_API void setFatalFunction(FatalFunction); + LL_COMMON_API void setFatalFunction(const FatalFunction&); // The fatal function will be called when an message of LEVEL_ERROR // is logged. Note: supressing a LEVEL_ERROR message from being logged // (by, for example, setting a class level to LEVEL_NONE), will keep // the that message from causing the fatal funciton to be invoked. - + + LL_COMMON_API FatalFunction getFatalFunction(); + // Retrieve the previously-set FatalFunction + + /// temporarily override the FatalFunction for the duration of a + /// particular scope, e.g. for unit tests + class LL_COMMON_API OverrideFatalFunction + { + public: + OverrideFatalFunction(const FatalFunction& func): + mPrev(getFatalFunction()) + { + setFatalFunction(func); + } + ~OverrideFatalFunction() + { + setFatalFunction(mPrev); + } + + private: + FatalFunction mPrev; + }; typedef std::string (*TimeFunction)(); LL_COMMON_API std::string utcTime(); diff --git a/indra/llcommon/llindraconfigfile.cpp b/indra/llcommon/llindraconfigfile.cpp index ca63e286e..f0873450f 100644 --- a/indra/llcommon/llindraconfigfile.cpp +++ b/indra/llcommon/llindraconfigfile.cpp @@ -45,7 +45,7 @@ static const char indraConfigFileName[] = "indra.xml"; LLIndraConfigFile::LLIndraConfigFile() - : LLLiveFile(filename(), configFileRefreshRate), + : LLLiveFile(filename()), mConfig(LLSD()) { } @@ -84,7 +84,7 @@ std::string LLIndraConfigFile::filename() } /* virtual */ -void LLIndraConfigFile::loadFile() +bool LLIndraConfigFile::loadFile() { llinfos << "LLIndraConfigFile::loadFile: reading from " << filename() << llendl; @@ -102,17 +102,18 @@ void LLIndraConfigFile::loadFile() { llinfos << "LLIndraConfigFile::loadFile: file missing, ill-formed," " or simply undefined; not changing the blacklist" << llendl; - return; + return false; } } if (config.isMap()) { mConfig = config; + return true; } else { llwarns << "LLIndraConfigFile: " << indraConfigFileName << " expects a map; wrong format" << llendl; - return; + return false; } } diff --git a/indra/llcommon/llindraconfigfile.h b/indra/llcommon/llindraconfigfile.h index 232e408da..661f79bd6 100644 --- a/indra/llcommon/llindraconfigfile.h +++ b/indra/llcommon/llindraconfigfile.h @@ -54,7 +54,7 @@ private: static std::string filename(); protected: - /* virtual */ void loadFile(); + /* virtual */ bool loadFile(); LLSD mConfig; }; diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp index e1bfc11a0..d2744875d 100644 --- a/indra/llcommon/llliveappconfig.cpp +++ b/indra/llcommon/llliveappconfig.cpp @@ -48,7 +48,7 @@ LLLiveAppConfig::~LLLiveAppConfig() { } // virtual -void LLLiveAppConfig::loadFile() +bool LLLiveAppConfig::loadFile() { llinfos << "LLLiveAppConfig::loadFile(): reading from " << filename() << llendl; @@ -59,12 +59,25 @@ void LLLiveAppConfig::loadFile() LLSDSerialize::fromXML(config, file); if(!config.isMap()) { - llinfos << "LLDataserverConfig::loadFile(): not an map!" + llwarns << "Live app config not an map in " << filename() << " Ignoring the data." << llendl; - return; + return false; } file.close(); } + else + { + llinfos << "Live file " << filename() << " does not exit." << llendl; + } + // *NOTE: we do not handle the else case here because we would not + // have attempted to load the file unless LLLiveFile had + // determined there was a reason to load it. This only happens + // when either the file has been updated or it is either suddenly + // in existence or has passed out of existence. Therefore, we want + // to set the config to an empty config, and return that it + // changed. + mApp->setOptionData( LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config); + return true; } diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h index 3251a7c50..465dde160 100644 --- a/indra/llcommon/llliveappconfig.h +++ b/indra/llcommon/llliveappconfig.h @@ -48,7 +48,7 @@ public: ~LLLiveAppConfig(); protected: - /*virtual*/ void loadFile(); + /*virtual*/ bool loadFile(); private: LLApp* mApp; diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index 810ae706a..322f226d5 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -35,6 +35,8 @@ #include "llframetimer.h" #include "lltimer.h" +const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f; + class LLLiveFile::Impl { public: @@ -42,7 +44,7 @@ public: ~Impl(); bool check(); - + void changed(); bool mForceCheck; F32 mRefreshPeriod; @@ -50,16 +52,19 @@ public: std::string mFilename; time_t mLastModTime; + time_t mLastStatTime; bool mLastExists; LLEventTimer* mEventTimer; }; -LLLiveFile::Impl::Impl(const std::string &filename, const F32 refresh_period) - : mForceCheck(true), +LLLiveFile::Impl::Impl(const std::string& filename, const F32 refresh_period) + : + mForceCheck(true), mRefreshPeriod(refresh_period), mFilename(filename), mLastModTime(0), + mLastStatTime(0), mLastExists(false), mEventTimer(NULL) { @@ -121,17 +126,29 @@ bool LLLiveFile::Impl::check() // We want to read the file. Update status info for the file. mLastExists = true; - mLastModTime = stat_data.st_mtime; - + mLastStatTime = stat_data.st_mtime; return true; } +void LLLiveFile::Impl::changed() +{ + // we wanted to read this file, and we were successful. + mLastModTime = mLastStatTime; +} bool LLLiveFile::checkAndReload() { bool changed = impl.check(); if (changed) { - loadFile(); + if(loadFile()) + { + impl.changed(); + this->changed(); + } + else + { + changed = false; + } } return changed; } @@ -167,3 +184,11 @@ void LLLiveFile::addToEventTimer() impl.mEventTimer = new LiveFileEventTimer(*this, impl.mRefreshPeriod); } +void LLLiveFile::setRefreshPeriod(F32 seconds) +{ + if (seconds < 0.f) + { + seconds = -seconds; + } + impl.mRefreshPeriod = seconds; +} diff --git a/indra/llcommon/lllivefile.h b/indra/llcommon/lllivefile.h index 72f16fd99..7480a8a8a 100644 --- a/indra/llcommon/lllivefile.h +++ b/indra/llcommon/lllivefile.h @@ -33,27 +33,65 @@ #ifndef LL_LLLIVEFILE_H #define LL_LLLIVEFILE_H -const F32 configFileRefreshRate = 5.0; // seconds +extern const F32 DEFAULT_CONFIG_FILE_REFRESH; class LL_COMMON_API LLLiveFile { public: - LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f); + LLLiveFile(const std::string& filename, const F32 refresh_period = DEFAULT_CONFIG_FILE_REFRESH); virtual ~LLLiveFile(); + /** + * @brief Check to see if this live file should reload. + * + * Call this before using anything that was read & cached + * from the file. + * + * This method calls the loadFile() method if + * any of: + * file has a new modify time since the last check + * file used to exist and now does not + * file used to not exist but now does + * @return Returns true if the file was reloaded. + */ bool checkAndReload(); - // Returns true if the file changed in any way - // Call this before using anything that was read & cached from the file + std::string filename() const; + /** + * @brief Add this live file to an automated recheck. + * + * Normally, just calling checkAndReload() is enough. In some + * cases though, you may need to let the live file periodically + * check itself. + */ void addToEventTimer(); - // Normally, just calling checkAndReload() is enough. In some cases - // though, you may need to let the live file periodically check itself. + + void setRefreshPeriod(F32 seconds); protected: - virtual void loadFile() = 0; // Implement this to load your file if it changed + /** + * @breif Implement this to load your file if it changed. + * + * This method is called automatically by checkAndReload(), + * so though you must implement this in derived classes, you do + * not need to call it manually. + * @return Returns true if the file was successfully loaded. + */ + virtual bool loadFile() = 0; + + /** + * @brief Implement this method if you want to get a change callback. + * + * This virtual function will be called automatically at the end + * of checkAndReload() if a new configuration was + * loaded. This does not track differences between the current and + * newly loaded file, so any successful load event will trigger a + * changed() callback. Default is to do nothing. + */ + virtual void changed() {} private: class Impl; diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index cbf5a2e1c..0583a0539 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -62,7 +62,7 @@ public: static std::string filename(); protected: - /* virtual */ void loadFile(); + /* virtual */ bool loadFile(); public: void init(LLPerfStats* statsp); @@ -94,12 +94,12 @@ LLStatsConfigFile& LLStatsConfigFile::instance() /* virtual */ // Load and parse the stats configuration file -void LLStatsConfigFile::loadFile() +bool LLStatsConfigFile::loadFile() { if (!mStatsp) { llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl; - return; + return false; } mChanged = true; @@ -113,7 +113,7 @@ void LLStatsConfigFile::loadFile() { llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl; mStatsp->setReportPerformanceDuration( 0.f ); - return; + return false; } } else @@ -123,7 +123,7 @@ void LLStatsConfigFile::loadFile() llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl; mStatsp->setReportPerformanceDuration( 0.f ); } - return; + return true; } } @@ -159,6 +159,7 @@ void LLStatsConfigFile::loadFile() { llinfos << "Performance stats recording turned off" << llendl; } + return true; } @@ -327,6 +328,7 @@ U64 LLStatAccum::sScaleTimes[NUM_SCALES] = LLStatAccum::LLStatAccum(bool useFrameTimer) : mUseFrameTimer(useFrameTimer), mRunning(FALSE), + mLastTime(0), mLastSampleValue(0.0), mLastSampleValid(FALSE) { @@ -347,7 +349,7 @@ void LLStatAccum::reset(U64 when) { mBuckets[i].accum = 0.0; mBuckets[i].endTime = when + sScaleTimes[i]; - mBuckets[i].lastValid = FALSE; + mBuckets[i].lastValid = false; } } @@ -395,7 +397,7 @@ void LLStatAccum::sum(F64 value, U64 when) { F64 valueLeft = value * timeLeft / timeSpan; - bucket.lastValid = TRUE; + bucket.lastValid = true; bucket.lastAccum = bucket.accum + (value - valueLeft); bucket.accum = valueLeft; bucket.endTime += timeScale; @@ -404,7 +406,7 @@ void LLStatAccum::sum(F64 value, U64 when) { U64 timeTail = timeLeft % timeScale; - bucket.lastValid = TRUE; + bucket.lastValid = true; bucket.lastAccum = value * timeScale / timeSpan; bucket.accum = value * timeTail / timeSpan; bucket.endTime += (timeLeft - timeTail) + timeScale; @@ -726,7 +728,6 @@ LLFrameTimer LLStat::sFrameTimer; LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) { llassert(num_bins > 0); - U32 i; mUseFrameTimer = use_frame_timer; mNumValues = 0; mLastValue = 0.f; @@ -738,7 +739,7 @@ LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) mBeginTime = new F64[mNumBins]; mTime = new F64[mNumBins]; mDT = new F32[mNumBins]; - for (i = 0; i < mNumBins; i++) + for (U32 i = 0; i < mNumBins; i++) { mBins[i] = 0.f; mBeginTime[i] = 0.0; diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index 951091b47..797e82b9e 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -96,11 +96,18 @@ public: struct Bucket { - F64 accum; - U64 endTime; + Bucket() : + accum(0.0), + endTime(0), + lastValid(false), + lastAccum(0.0) + {} - BOOL lastValid; - F64 lastAccum; + F64 accum; + U64 endTime; + + bool lastValid; + F64 lastAccum; }; Bucket mBuckets[NUM_SCALES]; diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 572890498..7aa37f150 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -91,6 +91,7 @@ set(llmessage_SOURCE_FILES llxfer_mem.cpp llxfer_vfile.cpp llxorcipher.cpp + machine.cpp message.cpp message_prehash.cpp message_string_table.cpp diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 34dfc9bdb..7a2dc6cc3 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -118,6 +118,7 @@ chan_(NULL), mInitSuccess(false) LLAres::~LLAres() { ares_destroy(chan_); + ares_library_cleanup(); } void LLAres::cancel() @@ -173,7 +174,8 @@ void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp) LLQueryResponder::LLQueryResponder() : LLAres::QueryResponder(), - mResult(ARES_ENODATA) + mResult(ARES_ENODATA), + mType(RES_INVALID) { } @@ -639,8 +641,10 @@ LLPtrRecord::LLPtrRecord(const std::string &name, unsigned ttl) } LLAddrRecord::LLAddrRecord(LLResType type, const std::string &name, - unsigned ttl) - : LLDnsRecord(type, name, ttl) + unsigned ttl) + : LLDnsRecord(type, name, ttl), + + mSize(0) { } @@ -699,7 +703,11 @@ bail: } LLSrvRecord::LLSrvRecord(const std::string &name, unsigned ttl) - : LLHostRecord(RES_SRV, name, ttl) + : LLHostRecord(RES_SRV, name, ttl), + + mPriority(0), + mWeight(0), + mPort(0) { } diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h index 96d7f6dd3..a8f4f0524 100644 --- a/indra/llmessage/llares.h +++ b/indra/llmessage/llares.h @@ -36,7 +36,13 @@ #define LL_LLARES_H #ifdef LL_WINDOWS +// ares.h is broken on windows in that it depends on types defined in ws2tcpip.h +// we need to include them first to work around it, but the headers issue warnings +# pragma warning(push) +# pragma warning(disable:4996) +# include # include +# pragma warning(pop) #endif #ifdef LL_STANDALONE diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 946c36ac6..523aa0e54 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -679,14 +679,12 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) std::map::iterator it = sCache.find(agent_id); if (it != sCache.end()) { - LLAvatarName& av_name = it->second; + const LLAvatarName& av_name = it->second; if (av_name.mExpires > LLFrameTimer::getTotalSeconds()) { - av_name.mDisplayName = av_name.mDisplayName; // ...name already exists in cache, fire callback now fireSignal(agent_id, slot, av_name); - return; } } @@ -698,7 +696,6 @@ void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot) if (gCacheName->getFullName(agent_id, full_name)) { LLAvatarName av_name; - av_name.mDisplayName = av_name.mDisplayName; buildLegacyName(full_name, &av_name); fireSignal(agent_id, slot, av_name); return; diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index 0ff5093ca..d0e57ac48 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -77,6 +77,8 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, mPacketsOutID(0), mPacketsInID(in_id), mHighestPacketID(in_id), + mTimeoutCallback(NULL), + mTimeoutUserData(NULL), mTrusted(FALSE), mbAllowTimeout(TRUE), mbAlive(TRUE), @@ -91,6 +93,7 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, mPingDelayAveraged((F32)INITIAL_PING_VALUE_MSEC), mUnackedPacketCount(0), mUnackedPacketBytes(0), + mLastPacketInTime(0.0), mLocalEndPointID(), mPacketsOut(0), mPacketsIn(0), @@ -102,11 +105,12 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, mBytesOutLastPeriod(0), mBytesInThisPeriod(0), mBytesOutThisPeriod(0), - mPeakBPSIn(0), - mPeakBPSOut(0), + mPeakBPSIn(0.f), + mPeakBPSOut(0.f), mPeriodTime(0.0), mExistenceTimer(), mCurrentResendCount(0), + mLastPacketGap(0), mHeartbeatInterval(circuit_heartbeat_interval), mHeartbeatTimeout(circuit_timeout) { @@ -121,9 +125,6 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id, mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval); mPeriodTime = mt_sec; - mTimeoutCallback = NULL; - mTimeoutUserData = NULL; - mLocalEndPointID.generate(); } @@ -673,6 +674,8 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) mHighestPacketID = llmax(mHighestPacketID, id); } + // Save packet arrival time + mLastPacketInTime = LLMessageSystem::getMessageTimeSeconds(); // Have we received anything on this circuit yet? if (0 == mPacketsIn) diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h index a259f49cf..711cba27c 100644 --- a/indra/llmessage/llcircuit.h +++ b/indra/llmessage/llcircuit.h @@ -136,6 +136,7 @@ public: { return mOutOfOrderRate.meanValue(scale); } U32 getLastPacketGap() const { return mLastPacketGap; } LLHost getHost() const { return mHost; } + F64 getLastPacketInTime() const { return mLastPacketInTime; } LLThrottleGroup &getThrottleGroup() { return mThrottles; } @@ -254,6 +255,7 @@ protected: S32 mUnackedPacketCount; S32 mUnackedPacketBytes; + F64 mLastPacketInTime; // Time of last packet arrival LLUUID mLocalEndPointID; diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 8c2909709..f43bafd45 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -76,7 +76,7 @@ ////////////////////////////////////////////////////////////////////////////// -static const S32 EASY_HANDLE_POOL_SIZE = 5; +static const U32 EASY_HANDLE_POOL_SIZE = 5; static const S32 MULTI_PERFORM_CALL_REPEAT = 5; static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; @@ -133,7 +133,7 @@ void LLCurl::Responder::errorWithContent( // virtual void LLCurl::Responder::error(U32 status, const std::string& reason) { - llinfos << status << ": " << reason << llendl; + llinfos << mURL << " [" << status << "]: " << reason << llendl; } // virtual @@ -141,6 +141,11 @@ void LLCurl::Responder::result(const LLSD& content) { } +void LLCurl::Responder::setURL(const std::string& url) +{ + mURL = url; +} + // virtual void LLCurl::Responder::completedRaw( U32 status, @@ -150,7 +155,10 @@ void LLCurl::Responder::completedRaw( { LLSD content; LLBufferStream istr(channels, buffer.get()); - LLSDSerialize::fromXML(content, istr); + if (!LLSDSerialize::fromXML(content, istr)) + { + llinfos << "Failed to deserialize LLSD. " << mURL << " [" << status << "]: " << reason << llendl; + } completed(status, reason, content); } @@ -491,6 +499,12 @@ void LLCurl::Easy::prepRequest(const std::string& url, setopt(CURLOPT_HEADERFUNCTION, (void*)&curlHeaderCallback); setopt(CURLOPT_HEADERDATA, (void*)this); + // Allow up to five redirects + if(responder && responder->followRedir()) + { + setopt(CURLOPT_FOLLOWLOCATION, 1); + setopt(CURLOPT_MAXREDIRS, MAX_REDIRECTS); + } setErrorBuffer(); setCA(); @@ -925,6 +939,15 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd } } +void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata) +{ + if (mEasy) + { + mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback); + mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); + } +} + void LLCurlEasyRequest::slist_append(const char* str) { if (mEasy) @@ -1075,3 +1098,4 @@ void LLCurl::cleanupClass() curl_global_cleanup(); } +const unsigned int LLCurl::MAX_REDIRECTS = 5; diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 32637b200..99ac1ffdd 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -120,8 +120,18 @@ public: // of the header can be parsed. In the ::completed call above only the body is contained in the LLSD. virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content); + // Used internally to set the url for debugging later. + void setURL(const std::string& url); + + virtual bool followRedir() + { + return false; + } public: /* but not really -- don't touch this */ U32 mReferenceCount; + + private: + std::string mURL; }; typedef boost::intrusive_ptr ResponderPtr; @@ -176,6 +186,7 @@ public: private: static std::string sCAPath; static std::string sCAFile; + static const unsigned int MAX_REDIRECTS; }; namespace boost @@ -223,6 +234,7 @@ public: void setHeaderCallback(curl_header_callback callback, void* userdata); void setWriteCallback(curl_write_callback callback, void* userdata); void setReadCallback(curl_read_callback callback, void* userdata); + void setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata); void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp index 1cdb475b2..9046f9c35 100644 --- a/indra/llmessage/lldatapacker.cpp +++ b/indra/llmessage/lldatapacker.cpp @@ -55,6 +55,18 @@ LLDataPacker::LLDataPacker() : mPassFlags(0), mWriteEnabled(FALSE) { } +//virtual +void LLDataPacker::reset() +{ + llerrs << "Using unimplemented datapacker reset!" << llendl; +} + +//virtual +void LLDataPacker::dumpBufferToLog() +{ + llerrs << "dumpBufferToLog not implemented for this type!" << llendl; +} + BOOL LLDataPacker::packFixed(const F32 value, const char *name, const BOOL is_signed, const U32 int_bits, const U32 frac_bits) { diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index 92bfec698..b8d9fcbdd 100644 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -45,8 +45,9 @@ class LLDataPacker public: virtual ~LLDataPacker() {} - virtual void reset() { llerrs << "Using unimplemented datapacker reset!" << llendl; }; - virtual void dumpBufferToLog() { llerrs << "dumpBufferToLog not implemented for this type!" << llendl; } + // Not required to override, but error to call? + virtual void reset(); + virtual void dumpBufferToLog(); virtual BOOL hasNext() const = 0; diff --git a/indra/llmessage/llhost.cpp b/indra/llmessage/llhost.cpp index 8e9e23393..238cf3e12 100644 --- a/indra/llmessage/llhost.cpp +++ b/indra/llmessage/llhost.cpp @@ -124,7 +124,7 @@ BOOL LLHost::setHostByName(const std::string& hostname) he = gethostbyname(local_name.c_str()); if(!he) { - U32 ip_address = inet_addr(hostname.c_str()); + U32 ip_address = ip_string_to_u32(hostname.c_str()); he = gethostbyaddr((char *)&ip_address, sizeof(ip_address), AF_INET); } diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 56d5c2399..e58df16bb 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -79,8 +79,10 @@ namespace { if (mResponder.get()) { - mResponder->completedRaw(mStatus, mReason, channels, buffer); + // Allow clients to parse headers before we attempt to parse + // the body and provide completed/result/error calls. mResponder->completedHeader(mStatus, mReason, mHeaderOutput); + mResponder->completedRaw(mStatus, mReason, channels, buffer); } } virtual void header(const std::string& header, const std::string& value) @@ -260,6 +262,11 @@ static void request( } } + if (responder) + { + responder->setURL(url); + } + req->setCallback(new LLHTTPClientURLAdaptor(responder)); if (method == LLURLRequest::HTTP_POST && gMessageSystem) @@ -339,20 +346,6 @@ void LLHTTPClient::get(const std::string& url, const LLSD& query, ResponderPtr r get(uri.asString(), responder, headers, timeout); } -class LLHTTPFileBuffer -{ -public: - llofstream * stream; - LLHTTPFileBuffer(llofstream * fstream):stream(fstream){} - static size_t curl_write( void *ptr, size_t size, size_t nmemb, void *user_data) - { - LLHTTPFileBuffer* self = (LLHTTPFileBuffer*)user_data; - size_t bytes = (size * nmemb); - self->stream->write((char*)ptr,bytes); - return nmemb; - } -}; - // A simple class for managing data returned from a curl http request. class LLHTTPBuffer { @@ -388,72 +381,139 @@ private: std::string mBuffer; }; -// *TODO: Deprecate (only used by dataserver) -// This call is blocking! This is probably usually bad. :( -LLSD LLHTTPClient::blockingGet(const std::string& url) +// These calls are blocking! This is usually bad, unless you're a dataserver. Then it's awesome. + +/** + @brief does a blocking request on the url, returning the data or bad status. + + @param url URI to verb on. + @param method the verb to hit the URI with. + @param body the body of the call (if needed - for instance not used for GET and DELETE, but is for POST and PUT) + @param headers HTTP headers to use for the request. + @param timeout Curl timeout to use. Defaults to 5. Rationale: + Without this timeout, blockingGet() calls have been observed to take + up to 90 seconds to complete. Users of blockingGet() already must + check the HTTP return code for validity, so this will not introduce + new errors. A 5 second timeout will succeed > 95% of the time (and + probably > 99% of the time) based on my statistics. JC + + @returns an LLSD map: {status: integer, body: map} + */ +static LLSD blocking_request( + const std::string& url, + LLURLRequest::ERequestAction method, + const LLSD& body, + const LLSD& headers = LLSD(), + const F32 timeout = 5 +) { - llinfos << "blockingGet of " << url << llendl; - - // Returns an LLSD map: {status: integer, body: map} - char curl_error_buffer[CURL_ERROR_SIZE]; + lldebugs << "blockingRequest of " << url << llendl; + char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; CURL* curlp = curl_easy_init(); - LLHTTPBuffer http_buffer; - - // Without this timeout, blockingGet() calls have been observed to take - // up to 90 seconds to complete. Users of blockingGet() already must - // check the HTTP return code for validity, so this will not introduce - // new errors. A 5 second timeout will succeed > 95% of the time (and - // probably > 99% of the time) based on my statistics. JC + std::string body_str; + + // other request method checks root cert first, we skip? + + // * Set curl handle options curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts - curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5); // seconds - + curl_easy_setopt(curlp, CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function. curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write); curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer); curl_easy_setopt(curlp, CURLOPT_URL, url.c_str()); curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer); - curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1); + + // * Setup headers (don't forget to free them after the call!) + curl_slist* headers_list = NULL; + if (headers.isMap()) + { + LLSD::map_const_iterator iter = headers.beginMap(); + LLSD::map_const_iterator end = headers.endMap(); + for (; iter != end; ++iter) + { + std::ostringstream header; + header << iter->first << ": " << iter->second.asString() ; + lldebugs << "header = " << header.str() << llendl; + headers_list = curl_slist_append(headers_list, header.str().c_str()); + } + } + + // * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy) + if (method == LLURLRequest::HTTP_GET) + { + curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1); + } + else if (method == LLURLRequest::HTTP_POST) + { + curl_easy_setopt(curlp, CURLOPT_POST, 1); + //serialize to ostr then copy to str - need to because ostr ptr is unstable :( + std::ostringstream ostr; + LLSDSerialize::toXML(body, ostr); + body_str = ostr.str(); + curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str()); + //copied from PHP libs, correct? + headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml"); - struct curl_slist *header_list = NULL; - header_list = curl_slist_append(header_list, "Accept: application/llsd+xml"); - CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, header_list); + // copied from llurlrequest.cpp + // it appears that apache2.2.3 or django in etch is busted. If + // we do not clear the expect header, we get a 500. May be + // limited to django/mod_wsgi. + headers_list = curl_slist_append(headers_list, "Expect:"); + } + + // * Do the action using curl, handle results + lldebugs << "HTTP body: " << body_str << llendl; + headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml"); + CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list); if ( curl_result != CURLE_OK ) { - llinfos << "Curl is hosed - can't add Accept header for llsd+xml" << llendl; + llinfos << "Curl is hosed - can't add headers" << llendl; } LLSD response = LLSD::emptyMap(); - S32 curl_success = curl_easy_perform(curlp); - S32 http_status = 499; - curl_easy_getinfo(curlp,CURLINFO_RESPONSE_CODE, &http_status); - + curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status); response["status"] = http_status; - - if (curl_success != 0 - && http_status != 404) // We expect 404s, don't spam for them. + // if we get a non-404 and it's not a 200 OR maybe it is but you have error bits, + if ( http_status != 404 && (http_status != 200 || curl_success != 0) ) { + // We expect 404s, don't spam for them. + llwarns << "CURL REQ URL: " << url << llendl; + llwarns << "CURL REQ METHOD TYPE: " << method << llendl; + llwarns << "CURL REQ HEADERS: " << headers.asString() << llendl; + llwarns << "CURL REQ BODY: " << body_str << llendl; + llwarns << "CURL HTTP_STATUS: " << http_status << llendl; llwarns << "CURL ERROR: " << curl_error_buffer << llendl; - + llwarns << "CURL ERROR BODY: " << http_buffer.asString() << llendl; response["body"] = http_buffer.asString(); } else { response["body"] = http_buffer.asLLSD(); + lldebugs << "CURL response: " << http_buffer.asString() << llendl; } - if(header_list) + if(headers_list) { // free the header list - curl_slist_free_all(header_list); - header_list = NULL; + curl_slist_free_all(headers_list); } + // * Cleanup curl_easy_cleanup(curlp); - return response; } +LLSD LLHTTPClient::blockingGet(const std::string& url) +{ + return blocking_request(url, LLURLRequest::HTTP_GET, LLSD()); +} + +LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body) +{ + return blocking_request(url, LLURLRequest::HTTP_POST, body); +} + void LLHTTPClient::put( const std::string& url, const LLSD& body, diff --git a/indra/llmessage/llhttpclient.h b/indra/llmessage/llhttpclient.h index a0c9fac77..3d0646e5f 100644 --- a/indra/llmessage/llhttpclient.h +++ b/indra/llmessage/llhttpclient.h @@ -142,6 +142,14 @@ public: */ static LLSD blockingGet(const std::string& url); + /** + * @brief Blocking HTTP POST that returns an LLSD map of status and body. + * + * @param url the complete serialized (and escaped) url to get + * @param body the LLSD post body + * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) } + */ + static LLSD blockingPost(const std::string& url, const LLSD& body); static void setPump(LLPumpIO& pump); diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h index 87f0c480f..7b7e18762 100644 --- a/indra/llmessage/llhttpnode.h +++ b/indra/llmessage/llhttpnode.h @@ -303,7 +303,7 @@ protected: ~LLSimpleResponse(); private: - LLSimpleResponse() {;} // Must be accessed through LLPointer. + LLSimpleResponse() : mCode(0) {} // Must be accessed through LLPointer. }; std::ostream& operator<<(std::ostream& out, const LLSimpleResponse& resp); diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index daeffb68f..018b649a6 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -61,6 +61,7 @@ const char EMPTY_BINARY_BUCKET[] = ""; const S32 EMPTY_BINARY_BUCKET_SIZE = 1; const U32 NO_TIMESTAMP = 0; const std::string SYSTEM_FROM("Second Life"); +const std::string INTERACTIVE_SYSTEM_FROM("F387446C-37C4-45f2-A438-D99CBDBB563B"); const S32 IM_TTL = 1; @@ -68,9 +69,11 @@ const S32 IM_TTL = 1; * LLIMInfo */ LLIMInfo::LLIMInfo() : + mFromGroup(FALSE), mParentEstateID(0), mOffline(0), mViewerThinksToIsOnline(false), + mIMType(IM_NOTHING_SPECIAL), mTimeStamp(0), mSource(IM_FROM_SIM), mTTL(IM_TTL) diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 96a2cf9ca..df8e0bebf 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -224,6 +224,7 @@ extern const S32 EMPTY_BINARY_BUCKET_SIZE; extern const U32 NO_TIMESTAMP; extern const std::string SYSTEM_FROM; +extern const std::string INTERACTIVE_SYSTEM_FROM; // Number of retry attempts on sending the im. extern const S32 IM_TTL; diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 83dfa94f0..27530fbfe 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -74,7 +74,12 @@ class LLHTTPPipe : public LLIOPipe { public: LLHTTPPipe(const LLHTTPNode& node) - : mNode(node), mResponse(NULL), mState(STATE_INVOKE), mChainLock(0), mStatusCode(0) + : mNode(node), + mResponse(NULL), + mState(STATE_INVOKE), + mChainLock(0), + mLockedPump(NULL), + mStatusCode(0) { } virtual ~LLHTTPPipe() { @@ -105,12 +110,13 @@ private: // from LLHTTPNode::Response virtual void result(const LLSD&); virtual void extendedResult(S32 code, const std::string& body, const LLSD& headers); + virtual void status(S32 code, const std::string& message); void nullPipe(); private: - Response() {;} // Must be accessed through LLPointer. + Response() : mPipe(NULL) {} // Must be accessed through LLPointer. LLHTTPPipe* mPipe; }; friend class Response; @@ -402,7 +408,7 @@ void LLHTTPPipe::unlockChain() class LLHTTPResponseHeader : public LLIOPipe { public: - LLHTTPResponseHeader() {} + LLHTTPResponseHeader() : mCode(0) {} virtual ~LLHTTPResponseHeader() {} protected: @@ -520,7 +526,7 @@ protected: * seek orfor string assignment. * @returns Returns true if a line was found. */ - bool readLine( + bool readHeaderLine( const LLChannelDescriptors& channels, buffer_ptr_t buffer, U8* dest, @@ -591,7 +597,7 @@ LLHTTPResponder::~LLHTTPResponder() //lldebugs << "destroying LLHTTPResponder" << llendl; } -bool LLHTTPResponder::readLine( +bool LLHTTPResponder::readHeaderLine( const LLChannelDescriptors& channels, buffer_ptr_t buffer, U8* dest, @@ -669,7 +675,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( #endif PUMP_DEBUG; - if(readLine(channels, buffer, (U8*)buf, len)) + if(readHeaderLine(channels, buffer, (U8*)buf, len)) { bool read_next_line = false; bool parse_all = true; @@ -733,7 +739,13 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl( if(read_next_line) { len = HEADER_BUFFER_SIZE; - readLine(channels, buffer, (U8*)buf, len); + if (!readHeaderLine(channels, buffer, (U8*)buf, len)) + { + // Failed to read the header line, probably too long. + // readHeaderLine already marked the channel/buffer as bad. + keep_parsing = false; + break; + } } if(0 == len) { diff --git a/indra/llmessage/lliohttpserver.h b/indra/llmessage/lliohttpserver.h index d1c9bdde8..e8e390f29 100644 --- a/indra/llmessage/lliohttpserver.h +++ b/indra/llmessage/lliohttpserver.h @@ -34,7 +34,6 @@ #ifndef LL_LLIOHTTPSERVER_H #define LL_LLIOHTTPSERVER_H -#include "llapr.h" #include "llchainio.h" #include "llhttpnode.h" diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index d52ff6c7e..ce206d8d7 100644 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -265,7 +265,7 @@ std::string LLMail::buildSMTPTransaction( // static bool LLMail::send( const std::string& header, - const std::string& message, + const std::string& raw_message, const char* from_address, const char* to_address) { @@ -276,8 +276,20 @@ bool LLMail::send( return false; } - // *FIX: this translation doesn't deal with a single period on a - // line by itself. + // remove any "." SMTP commands to prevent injection (DEV-35777) + // we don't need to worry about "\r\n.\r\n" because of the + // "\n" --> "\n\n" conversion going into rfc2822_msg below + std::string message = raw_message; + std::string bad_string = "\n.\n"; + std::string good_string = "\n..\n"; + while (1) + { + int index = message.find(bad_string); + if (index == std::string::npos) break; + message.replace(index, bad_string.size(), good_string); + } + + // convert all "\n" into "\r\n" std::ostringstream rfc2822_msg; for(U32 i = 0; i < message.size(); ++i) { diff --git a/indra/llmessage/llmessageconfig.cpp b/indra/llmessage/llmessageconfig.cpp index d4279354b..dff0a3844 100644 --- a/indra/llmessage/llmessageconfig.cpp +++ b/indra/llmessage/llmessageconfig.cpp @@ -66,7 +66,7 @@ public: static LLMessageConfigFile& instance(); // return the singleton configuration file - /* virtual */ void loadFile(); + /* virtual */ bool loadFile(); void loadServerDefaults(const LLSD& data); void loadMaxQueuedEvents(const LLSD& data); void loadMessages(const LLSD& data); @@ -98,7 +98,7 @@ LLMessageConfigFile& LLMessageConfigFile::instance() } // virtual -void LLMessageConfigFile::loadFile() +bool LLMessageConfigFile::loadFile() { LLSD data; { @@ -115,7 +115,7 @@ void LLMessageConfigFile::loadFile() LL_INFOS("AppInit") << "LLMessageConfigFile::loadFile: file missing," " ill-formed, or simply undefined; not changing the" " file" << LL_ENDL; - return; + return false; } } loadServerDefaults(data); @@ -123,6 +123,7 @@ void LLMessageConfigFile::loadFile() loadMessages(data); loadCapBans(data); loadMessageBans(data); + return true; } void LLMessageConfigFile::loadServerDefaults(const LLSD& data) diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h index d7f02ebd8..8abc0aaab 100644 --- a/indra/llmessage/llmessagetemplate.h +++ b/indra/llmessage/llmessagetemplate.h @@ -82,7 +82,7 @@ protected: class LLMsgBlkData { public: - LLMsgBlkData(const char *name, S32 blocknum) : mOffset(-1), mBlockNumber(blocknum), mTotalSize(-1) + LLMsgBlkData(const char *name, S32 blocknum) : mBlockNumber(blocknum), mTotalSize(-1) { mName = (char *)name; } @@ -108,7 +108,6 @@ public: temp->addData(data, size, type, data_size); } - S32 mOffset; S32 mBlockNumber; typedef LLDynamicArrayIndexed msg_var_data_map_t; msg_var_data_map_t mMemberVarData; @@ -136,7 +135,6 @@ public: void addDataFast(char *blockname, char *varname, const void *data, S32 size, EMsgVariableType type, S32 data_size = -1); public: - S32 mOffset; typedef std::map msg_blk_data_map_t; msg_blk_data_map_t mMemberBlocks; char *mName; diff --git a/indra/llmessage/llservicebuilder.cpp b/indra/llmessage/llservicebuilder.cpp index 194c4e257..51404a35b 100644 --- a/indra/llmessage/llservicebuilder.cpp +++ b/indra/llmessage/llservicebuilder.cpp @@ -44,7 +44,7 @@ void LLServiceBuilder::loadServiceDefinitionsFromFile( if(service_file.is_open()) { LLSD service_data; - LLSDSerialize::fromXML(service_data, service_file); + LLSDSerialize::fromXMLDocument(service_data, service_file); service_file.close(); // Load service LLSD service_map = service_data["services"]; diff --git a/indra/llmessage/lltemplatemessagebuilder.cpp b/indra/llmessage/lltemplatemessagebuilder.cpp index 7dbcedce8..fa02456d9 100644 --- a/indra/llmessage/lltemplatemessagebuilder.cpp +++ b/indra/llmessage/lltemplatemessagebuilder.cpp @@ -728,7 +728,7 @@ static S32 buildBlock(U8* buffer, S32 buffer_size, const LLMessageBlock* templat // out gracefully from this function. XXXTBD llerrs << "buildBlock failed. " << "Attempted to pack " - << result + mvci.getSize() + << (result + mvci.getSize()) << " bytes into a buffer with size " << buffer_size << "." << llendl; } diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp index 70279a3c6..0872efba5 100644 --- a/indra/llmessage/llthrottle.cpp +++ b/indra/llmessage/llthrottle.cpp @@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec) return changed; } +// Return bits available in the channel +S32 LLThrottleGroup::getAvailable(S32 throttle_cat) +{ + S32 retval = 0; + + F32 category_bps = mCurrentBPS[throttle_cat]; + F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME; + + // use a temporary bits_available + // since we don't want to change mBitsAvailable every time + F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]); + F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time); + + if (bits_available >= lookahead_bits) + { + retval = (S32) gThrottleMaximumBPS[throttle_cat]; + } + else + { + retval = (S32) bits_available; + } + + return retval; +} + BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits) { diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h index 7d1679beb..47a7c653b 100644 --- a/indra/llmessage/llthrottle.h +++ b/indra/llmessage/llthrottle.h @@ -84,6 +84,8 @@ public: BOOL dynamicAdjust(); // Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred BOOL setNominalBPS(F32* throttle_vec); // TRUE if any value was different, resets adjustment system if was different + S32 getAvailable(S32 throttle_cat); // Return bits available in the channel + void packThrottle(LLDataPacker &dp) const; void unpackThrottle(LLDataPacker &dp); public: diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index d67911e8e..2df64b7cd 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -1195,6 +1195,7 @@ LLTransferTarget::LLTransferTarget( mType(type), mSourceType(source_type), mID(transfer_id), + mChannelp(NULL), mGotInfo(FALSE), mSize(0), mLastPacketID(-1) diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index d1bfeb4fc..9b562f451 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -60,7 +60,7 @@ void LLTransferSourceAsset::initTransfer() // to the simulator. This is subset of assets we allow to be // simply pulled straight from the asset system. LLUUID* tidp; - if(is_asset_fetch_by_id_allowed(mParams.getAssetType())) + if(LLAssetType::lookupIsAssetFetchByIDAllowed(mParams.getAssetType())) { tidp = new LLUUID(getID()); gAssetStorage->getAssetData( @@ -226,7 +226,10 @@ void LLTransferSourceAsset::responderCallback(LLVFS *vfs, const LLUUID& uuid, LL -LLTransferSourceParamsAsset::LLTransferSourceParamsAsset() : LLTransferSourceParams(LLTST_ASSET) +LLTransferSourceParamsAsset::LLTransferSourceParamsAsset() + : LLTransferSourceParams(LLTST_ASSET), + + mAssetType(LLAssetType::AT_NONE) { } @@ -254,50 +257,3 @@ BOOL LLTransferSourceParamsAsset::unpackParams(LLDataPacker &dp) return TRUE; } - -/** - * Helper functions - */ -bool is_asset_fetch_by_id_allowed(LLAssetType::EType type) -{ - // *FIX: Make this list smaller. - bool rv = false; - switch(type) - { - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - rv = true; - break; - default: - break; - } - return rv; -} - -bool is_asset_id_knowable(LLAssetType::EType type) -{ - // *FIX: Make this list smaller. - bool rv = false; - switch(type) - { - case LLAssetType::AT_TEXTURE: - case LLAssetType::AT_SOUND: - case LLAssetType::AT_LANDMARK: - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_NOTECARD: - case LLAssetType::AT_BODYPART: - case LLAssetType::AT_ANIMATION: - case LLAssetType::AT_GESTURE: - case LLAssetType::AT_LINK: - case LLAssetType::AT_LINK_FOLDER: - rv = true; - break; - default: - break; - } - return rv; -} diff --git a/indra/llmessage/lltransfersourceasset.h b/indra/llmessage/lltransfersourceasset.h index 70b09b6aa..861659565 100644 --- a/indra/llmessage/lltransfersourceasset.h +++ b/indra/llmessage/lltransfersourceasset.h @@ -84,24 +84,4 @@ protected: S32 mCurPos; }; -/** - * @brief Quick check to see if the asset allows direct download. - * - * This might not be the right place for this function call, but it - * originally started life inside the LLTransferSourceAsset code. - * @param type The type of asset. - * @return Returns true if the asset can be fetched by id. - */ -bool is_asset_fetch_by_id_allowed(LLAssetType::EType type); - -/** - * @brief Quick check to see if all asset data can be known by the viewer. - * - * This might not be the right place for this function call, but it - * originally started life inside the LLTransferSourceAsset code. - * @param type The type of asset. - * @return Returns true if the asset id can be transmitted to the viewer. - */ -bool is_asset_id_knowable(LLAssetType::EType type); - #endif // LL_LLTRANSFERSOURCEASSET_H diff --git a/indra/llmessage/lltransfertargetfile.h b/indra/llmessage/lltransfertargetfile.h index 18b9b5206..92fb8f807 100644 --- a/indra/llmessage/lltransfertargetfile.h +++ b/indra/llmessage/lltransfertargetfile.h @@ -40,7 +40,12 @@ typedef void (*LLTTFCompleteCallback)(const LLTSCode status, void *user_data); class LLTransferTargetParamsFile : public LLTransferTargetParams { public: - LLTransferTargetParamsFile() : LLTransferTargetParams(LLTTT_FILE) {} + LLTransferTargetParamsFile() + : LLTransferTargetParams(LLTTT_FILE), + + mCompleteCallback(NULL), + mUserData(NULL) + {} void setFilename(const std::string& filename) { mFilename = filename; } void setCallback(LLTTFCompleteCallback cb, void *user_data) { mCompleteCallback = cb; mUserData = user_data; } diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h index 8c2bc7e8b..cd18d8ce3 100644 --- a/indra/llmessage/lltransfertargetvfile.h +++ b/indra/llmessage/lltransfertargetvfile.h @@ -68,7 +68,6 @@ protected: LLTTVFCompleteCallback mCompleteCallback; void* mUserDatap; S32 mErrCode; - LLVFSThread::handle_t mHandle; }; diff --git a/indra/llmessage/llxfer.cpp b/indra/llmessage/llxfer.cpp index 8404f6519..7aa833ee3 100644 --- a/indra/llmessage/llxfer.cpp +++ b/indra/llmessage/llxfer.cpp @@ -74,6 +74,7 @@ void LLXfer::init (S32 chunk_size) mCallback = NULL; mCallbackDataHandle = NULL; + mCallbackResult = 0; mBufferContainsEOF = FALSE; mBuffer = NULL; diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index 08c9192c9..209bdb224 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -760,30 +760,36 @@ static bool remove_prefix(std::string& filename, const std::string& prefix) static bool verify_cache_filename(const std::string& filename) { //NOTE: This routine is only used to check file names that our own - // code places in the cache directory. As such, it can be limited - // to this very restrictive file name pattern. It does not need to - // handle other characters. - + // code places in the cache directory. As such, it can be limited + // to this very restrictive file name pattern. It does not need to + // handle other characters. The only known uses of this are (with examples): + // sim to sim object pass: fc0b72d8-9456-63d9-a802-a557ef847313.tmp + // sim to viewer mute list: mute_b78eacd0-1244-448e-93ca-28ede242f647.tmp + // sim to viewer task inventory: inventory_d8ab59d2-baf0-0e79-c4c2-a3f99b9fcf45.tmp + + //IMPORTANT: Do not broaden the filenames accepted by this routine + // without careful analysis. Anything allowed by this function can + // be downloaded by the viewer. + size_t len = filename.size(); - //const boost::regex expr("[a-zA-Z0-9][-_.a-zA-Z0-9]<0,49>"); - if (len < 1 || len > 50) - { + //const boost::regex expr("[0-9a-zA-Z_-]<1,46>\.tmp"); + if (len < 5 || len > 50) + { return false; } - for(unsigned i=0; i 0) - { - ok = '_'==c || '-'==c || '.'==c; - } + bool ok = isalnum(c) || '_'==c || '-'==c; if (!ok) { return false; } } - return true; + return filename[len-4] == '.' + && filename[len-3] == 't' + && filename[len-2] == 'm' + && filename[len-1] == 'p'; } void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user_data*/) diff --git a/indra/llmessage/machine.cpp b/indra/llmessage/machine.cpp new file mode 100644 index 000000000..297ea58a3 --- /dev/null +++ b/indra/llmessage/machine.cpp @@ -0,0 +1,63 @@ +/** + * @file machine.cpp + * @brief LLMachine class header file + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + * + */ +#include "linden_common.h" + +#include "machine.h" + +#include "llerror.h" + +void LLMachine::setMachinePort(S32 port) +{ + if (port < 0) + { + llinfos << "Can't assign a negative number to LLMachine::mPort" << llendl; + mHost.setPort(0); + } + else + { + mHost.setPort(port); + } +} + +void LLMachine::setControlPort( S32 port ) +{ + if (port < 0) + { + llinfos << "Can't assign a negative number to LLMachine::mControlPort" << llendl; + mControlPort = 0; + } + else + { + mControlPort = port; + } +} diff --git a/indra/llmessage/machine.h b/indra/llmessage/machine.h index 63a038159..6da8e5e04 100644 --- a/indra/llmessage/machine.h +++ b/indra/llmessage/machine.h @@ -33,7 +33,6 @@ #ifndef LL_MACHINE_H #define LL_MACHINE_H -#include "llerror.h" #include "net.h" #include "llhost.h" @@ -79,31 +78,8 @@ public: void setMachineIP(U32 ip) { mHost.setAddress(ip); } void setMachineHost(const LLHost &host) { mHost = host; } - void setMachinePort(S32 port) - { - if (port < 0) - { - llinfos << "Can't assign a negative number to LLMachine::mPort" << llendl; - mHost.setPort(0); - } - else - { - mHost.setPort(port); - } - } - - void setControlPort( S32 port ) - { - if (port < 0) - { - llinfos << "Can't assign a negative number to LLMachine::mControlPort" << llendl; - mControlPort = 0; - } - else - { - mControlPort = port; - } - } + void setMachinePort(S32 port); + void setControlPort( S32 port ); // member variables diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 3ea94c52b..677052d65 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -257,6 +257,8 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, { init(); + mSendSize = 0; + mSystemVersionMajor = version_major; mSystemVersionMinor = version_minor; mSystemVersionPatch = version_patch; @@ -327,6 +329,8 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, mMaxMessageTime = 1.f; mTrueReceiveSize = 0; + + mReceiveTime = 0.f; } diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 93ed6e044..3906dfa53 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -84,6 +84,7 @@ typedef int socklen_t; static U32 gsnReceivingIFAddr = INVALID_HOST_IP_ADDRESS; // Address to which datagram was sent const char* LOOPBACK_ADDRESS_STRING = "127.0.0.1"; +const char* BROADCAST_ADDRESS_STRING = "255.255.255.255"; #if LL_DARWIN // Mac OS X returns an error when trying to set these to 400000. Smaller values succeed. @@ -171,7 +172,21 @@ char *u32_to_ip_string(U32 ip, char *ip_string) // Wrapper for inet_addr() U32 ip_string_to_u32(const char* ip_string) { - return inet_addr(ip_string); + // *NOTE: Windows doesn't support inet_aton(), so we are using + // inet_addr(). Unfortunately, INADDR_NONE == INADDR_BROADCAST, so + // we have to check whether the input is a broadcast address before + // deciding that @ip_string is invalid. + // + // Also, our definition of INVALID_HOST_IP_ADDRESS doesn't allow us to + // use wildcard addresses. -Ambroff + U32 ip = inet_addr(ip_string); + if (ip == INADDR_NONE + && strncmp(ip_string, BROADCAST_ADDRESS_STRING, MAXADDRSTR) != 0) + { + llwarns << "ip_string_to_u32() failed, Error: Invalid IP string '" << ip_string << "'" << llendl; + return INVALID_HOST_IP_ADDRESS; + } + return ip; } @@ -378,9 +393,10 @@ S32 start_net(S32& socket_out, int& nPort) LL_DEBUGS("AppInit") << "startNet - send buffer size : " << snd_size << LL_ENDL; // Setup a destination address - char achMCAddr[MAXADDRSTR] = " "; /* Flawfinder: ignore */ + //char achMCAddr[MAXADDRSTR] = " "; /* Flawfinder: ignore */ stDstAddr.sin_family = AF_INET; - stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr); + //stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr); + stDstAddr.sin_addr.s_addr = INVALID_HOST_IP_ADDRESS; //Not so sure about this... stDstAddr.sin_port = htons(nPort); socket_out = hSocket; @@ -659,7 +675,7 @@ S32 start_net(S32& socket_out, int& nPort) // Setup a destination address char achMCAddr[MAXADDRSTR] = "127.0.0.1"; /* Flawfinder: ignore */ stDstAddr.sin_family = AF_INET; - stDstAddr.sin_addr.s_addr = inet_addr(achMCAddr); + stDstAddr.sin_addr.s_addr = ip_string_to_u32(achMCAddr); stDstAddr.sin_port = htons(nPort); socket_out = hSocket; diff --git a/indra/llmessage/net.h b/indra/llmessage/net.h index 531b5c358..4c5688ebd 100644 --- a/indra/llmessage/net.h +++ b/indra/llmessage/net.h @@ -63,6 +63,7 @@ char* u32_to_ip_string(U32 ip, char *ip_string); // NULL on failure, ip_string U32 ip_string_to_u32(const char* ip_string); // Wrapper for inet_addr() extern const char* LOOPBACK_ADDRESS_STRING; +extern const char* BROADCAST_ADDRESS_STRING; void tcp_close_channel(S32 handle); S32 tcp_open_channel(LLHost host); diff --git a/indra/llmessage/sound_ids.cpp b/indra/llmessage/sound_ids.cpp index b31fba52f..028ef8fc1 100644 --- a/indra/llmessage/sound_ids.cpp +++ b/indra/llmessage/sound_ids.cpp @@ -32,6 +32,8 @@ #include "sound_ids.h" +#include "lluuid.h" + LLUUID const SND_NULL = LLUUID::null; LLUUID const SND_RIDE ("00000000-0000-0000-0000-000000000100"); LLUUID const SND_SHOT ("00000000-0000-0000-0000-000000000101"); diff --git a/indra/llmessage/sound_ids.h b/indra/llmessage/sound_ids.h index 038e857da..aa50a2b88 100644 --- a/indra/llmessage/sound_ids.h +++ b/indra/llmessage/sound_ids.h @@ -33,31 +33,31 @@ #ifndef LL_SOUND_IDS_H #define LL_SOUND_IDS_H -#include "lluuid.h" +// *NOTE: Do not put the actual IDs in this file - otherwise the symbols +// and values will be copied into every .o/.obj file and increase link time. -extern LLUUID const SND_NULL; +class LLUUID; + +extern const LLUUID SND_NULL; extern LLUUID const SND_RIDE; extern LLUUID const SND_SHOT; extern LLUUID const SND_MORTAR; -extern LLUUID const SND_HIT; -extern LLUUID const SND_EXPLOSION; -extern LLUUID const SND_BOING; -extern LLUUID const SND_OBJECT_CREATE; +extern const LLUUID SND_HIT; +extern const LLUUID SND_EXPLOSION; +extern const LLUUID SND_BOING; +extern const LLUUID SND_OBJECT_CREATE; -// // Different bird sounds for different states -// - -extern LLUUID const SND_CHIRP; -extern LLUUID const SND_CHIRP2; -extern LLUUID const SND_CHIRP3; -extern LLUUID const SND_CHIRP4; -extern LLUUID const SND_CHIRP5; -extern LLUUID const SND_CHIRPDEAD; +extern const LLUUID SND_CHIRP; // Flying random chirp +extern const LLUUID SND_CHIRP2; // Spooked by user +extern const LLUUID SND_CHIRP3; // Spooked by object +extern const LLUUID SND_CHIRP4; // Chasing other bird +extern const LLUUID SND_CHIRP5; // Hopping random chirp +extern const LLUUID SND_CHIRPDEAD; // Hit by grenade - dead! -extern LLUUID const SND_MUNCH; -extern LLUUID const SND_PUNCH; +extern const LLUUID SND_MUNCH; +extern const LLUUID SND_PUNCH; extern LLUUID const SND_SPLASH; extern LLUUID const SND_CLICK; extern LLUUID const SND_WHISTLE;