diff options
Diffstat (limited to 'indra/llmessage')
-rw-r--r-- | indra/llmessage/llcurl.cpp | 343 | ||||
-rw-r--r-- | indra/llmessage/llcurl.h | 118 | ||||
-rw-r--r-- | indra/llmessage/llpartdata.cpp | 14 | ||||
-rw-r--r-- | indra/llmessage/llpartdata.h | 3 | ||||
-rw-r--r-- | indra/llmessage/llpumpio.cpp | 2 | ||||
-rw-r--r-- | indra/llmessage/lltransfermanager.cpp | 7 | ||||
-rw-r--r-- | indra/llmessage/lltransfertargetvfile.cpp | 58 | ||||
-rw-r--r-- | indra/llmessage/lltransfertargetvfile.h | 2 | ||||
-rw-r--r-- | indra/llmessage/message.h | 1 |
9 files changed, 495 insertions, 53 deletions
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp new file mode 100644 index 0000000000..886697ed41 --- /dev/null +++ b/indra/llmessage/llcurl.cpp @@ -0,0 +1,343 @@ +/* + * llcurl.cpp + * MacTester + * + * Created by Zero Linden on 10/15/06. + * Copyright 2006 __MyCompanyName__. All rights reserved. + * + */ + +#include "llcurl.h" + +#include <iomanip> + +#include "llsdserialize.h" + +////////////////////////////////////////////////////////////////////////////// +/* + The trick to getting curl to do keep-alives is to reuse the + same easy handle for the requests. It appears that curl + keeps a pool of connections alive for each easy handle, but + doesn't share them between easy handles. Therefore it is + important to keep a pool of easy handles and reuse them, + rather than create and destroy them with each request. This + code does this. + + Furthermore, it would behoove us to keep track of which + hosts an easy handle was used for and pick an easy handle + that matches the next request. This code does not current + do this. + */ + +using namespace std; + +LLCurl::Responder::Responder() + : mReferenceCount(0) +{ +} +LLCurl::Responder::~Responder() +{ +} + +// virtual +void LLCurl::Responder::error(U32 status, const std::stringstream& content) +{ + llinfos << "LLCurl::Responder::error " << status << ": " << content.str() << llendl; +} + +// virtual +void LLCurl::Responder::result(const std::stringstream& content) +{ +} + +// virtual +void LLCurl::Responder::completed(U32 status, const std::stringstream& content) +{ + if (200 <= status && status < 300) + { + result(content); + } + else + { + error(status, content); + } +} + + +namespace boost +{ + void intrusive_ptr_add_ref(LLCurl::Responder* p) + { + ++p->mReferenceCount; + } + + void intrusive_ptr_release(LLCurl::Responder* p) + { + if(0 == --p->mReferenceCount) + { + delete p; + } + } +}; + +////////////////////////////////////////////////////////////////////////////// + +size_t +curlOutputCallback(void* data, size_t size, size_t nmemb, void* user_data) +{ + stringstream& output = *(stringstream*)user_data; + + size_t n = size * nmemb; + output.write((const char*)data, n); + if (!((istream&)output).good()) { + std::cerr << "WHAT!?!?!? istream side bad" << std::endl; + } + if (!((ostream&)output).good()) { + std::cerr << "WHAT!?!?!? ostream side bad" << std::endl; + } + + return n; +} + +// Only used if request contained a body (post or put), Not currently implemented. +// size_t +// curlRequestCallback(void* data, size_t size, size_t nmemb, void* user_data) +// { +// stringstream& request = *(stringstream*)user_data; + +// size_t n = size * nmemb; +// request.read((char*)data, n); +// return request.gcount(); +// } + + + + + +LLCurl::Easy::Easy() +{ + mHeaders = 0; + mHeaders = curl_slist_append(mHeaders, "Connection: keep-alive"); + mHeaders = curl_slist_append(mHeaders, "Keep-alive: 300"); + mHeaders = curl_slist_append(mHeaders, "Content-Type: application/xml"); + // FIXME: shouldn't be there for GET/DELETE + // FIXME: should have ACCEPT headers + + mHandle = curl_easy_init(); +} + +LLCurl::Easy::~Easy() +{ + curl_easy_cleanup(mHandle); + curl_slist_free_all(mHeaders); +} + +void +LLCurl::Easy::get(const string& url, ResponderPtr responder) +{ + prep(url, responder); + curl_easy_setopt(mHandle, CURLOPT_HTTPGET, 1); +} + +void +LLCurl::Easy::getByteRange(const string& url, S32 offset, S32 length, ResponderPtr responder) +{ + mRange = llformat("Range: bytes=%d-%d", offset,offset+length-1); + mHeaders = curl_slist_append(mHeaders, mRange.c_str()); + prep(url, responder); + curl_easy_setopt(mHandle, CURLOPT_HTTPGET, 1); +} + +void +LLCurl::Easy::perform() +{ + report(curl_easy_perform(mHandle)); +} + +void +LLCurl::Easy::prep(const std::string& url, ResponderPtr responder) +{ +#if !LL_DARWIN + curl_easy_reset(mHandle); // SJB: doesn't exisit on OSX 10.3.9 +#else + // SJB: equivalent? fast? + curl_easy_cleanup(mHandle); + mHandle = curl_easy_init(); +#endif + + curl_easy_setopt(mHandle, CURLOPT_PRIVATE, this); + +// curl_easy_setopt(mHandle, CURLOPT_VERBOSE, 1); // usefull for debugging + curl_easy_setopt(mHandle, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(mHandle, CURLOPT_WRITEFUNCTION, &curlOutputCallback); + curl_easy_setopt(mHandle, CURLOPT_WRITEDATA, &mOutput); +#if 1 // For debug + curl_easy_setopt(mHandle, CURLOPT_HEADERFUNCTION, &curlOutputCallback); + curl_easy_setopt(mHandle, CURLOPT_HEADERDATA, &mHeaderOutput); +#endif + curl_easy_setopt(mHandle, CURLOPT_ERRORBUFFER, &mErrorBuffer); + curl_easy_setopt(mHandle, CURLOPT_ENCODING, ""); + curl_easy_setopt(mHandle, CURLOPT_SSL_VERIFYPEER, false); + curl_easy_setopt(mHandle, CURLOPT_HTTPHEADER, mHeaders); + + mOutput.str(""); + if (!((istream&)mOutput).good()) { + std::cerr << "WHAT!?!?!? istream side bad" << std::endl; + } + if (!((ostream&)mOutput).good()) { + std::cerr << "WHAT!?!?!? ostream side bad" << std::endl; + } + + mURL = url; + curl_easy_setopt(mHandle, CURLOPT_URL, mURL.c_str()); + + mResponder = responder; +} + +void +LLCurl::Easy::report(CURLcode code) +{ + if (!mResponder) return; + + long responseCode; + + if (code == CURLE_OK) + { + curl_easy_getinfo(mHandle, CURLINFO_RESPONSE_CODE, &responseCode); + } + else + { + responseCode = 499; + } + + mResponder->completed(responseCode, mOutput); + mResponder = NULL; +} + + + + + + +LLCurl::Multi::Multi() +{ + mHandle = curl_multi_init(); +} + +LLCurl::Multi::~Multi() +{ + // FIXME: should clean up excess handles in mFreeEasy + curl_multi_cleanup(mHandle); +} + + +void +LLCurl::Multi::get(const std::string& url, ResponderPtr responder) +{ + LLCurl::Easy* easy = easyAlloc(); + easy->get(url, responder); + curl_multi_add_handle(mHandle, easy->mHandle); +} + +void +LLCurl::Multi::getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr responder) +{ + LLCurl::Easy* easy = easyAlloc(); + easy->getByteRange(url, offset, length, responder); + curl_multi_add_handle(mHandle, easy->mHandle); +} + +void +LLCurl::Multi::process() +{ + int count; + for (int call_count = 0; call_count < 5; call_count += 1) + { + if (CURLM_CALL_MULTI_PERFORM != curl_multi_perform(mHandle, &count)) + { + break; + } + } + + CURLMsg* msg; + int msgs_in_queue; + while ((msg = curl_multi_info_read(mHandle, &msgs_in_queue))) + { + if (msg->msg != CURLMSG_DONE) continue; + Easy* easy = 0; + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &easy); + if (!easy) continue; + easy->report(msg->data.result); + + curl_multi_remove_handle(mHandle, easy->mHandle); + easyFree(easy); + } +} + + + +LLCurl::Easy* +LLCurl::Multi::easyAlloc() +{ + Easy* easy = 0; + + if (mFreeEasy.empty()) + { + easy = new Easy(); + } + else + { + easy = mFreeEasy.back(); + mFreeEasy.pop_back(); + } + + return easy; +} + +void +LLCurl::Multi::easyFree(Easy* easy) +{ + if (mFreeEasy.size() < 5) + { + mFreeEasy.push_back(easy); + } + else + { + delete easy; + } +} + + + +namespace +{ + static LLCurl::Multi* sMainMulti = 0; + + LLCurl::Multi* + mainMulti() + { + if (!sMainMulti) { + sMainMulti = new LLCurl::Multi(); + } + return sMainMulti; + } +} + +void +LLCurl::get(const std::string& url, ResponderPtr responder) +{ + mainMulti()->get(url, responder); +} + +void +LLCurl::getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr responder) +{ + mainMulti()->getByteRange(url, offset, length, responder); +} + +void +LLCurl::process() +{ + mainMulti()->process(); +} + diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h new file mode 100644 index 0000000000..4f1b5e6031 --- /dev/null +++ b/indra/llmessage/llcurl.h @@ -0,0 +1,118 @@ +/* + * llcurl.h + * MacTester + * + * Created by Zero Linden on 10/15/06. + * Copyright 2006 __MyCompanyName__. All rights reserved. + * + */ + +#ifndef LL_LLCURL_H +#define LL_LLCURL_H + +#include "linden_common.h" + +#include <sstream> +#include <string> +#include <vector> + +#include <boost/intrusive_ptr.hpp> +#include <curl/curl.h> + +// #include "llhttpclient.h" + +class LLCurl +{ +public: + class Multi; + + class Responder + { + public: + Responder(); + virtual ~Responder(); + + virtual void error(U32 status, const std::stringstream& content); // called with bad status codes + + virtual void result(const std::stringstream& content); + + virtual void completed(U32 status, const std::stringstream& content); + /**< The default implemetnation calls + either: + * result(), or + * error() + */ + + public: /* but not really -- don't touch this */ + U32 mReferenceCount; + }; + typedef boost::intrusive_ptr<Responder> ResponderPtr; + + class Easy + { + public: + Easy(); + ~Easy(); + + void get(const std::string& url, ResponderPtr); + void getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr); + + void perform(); + + private: + void prep(const std::string& url, ResponderPtr); + void report(CURLcode); + + CURL* mHandle; + struct curl_slist* mHeaders; + + std::string mURL; + std::string mRange; + std::stringstream mRequest; + + std::stringstream mOutput; + char mErrorBuffer[CURL_ERROR_SIZE]; + + std::stringstream mHeaderOutput; // Debug + + ResponderPtr mResponder; + + friend class Multi; + }; + + + class Multi + { + public: + Multi(); + ~Multi(); + + void get(const std::string& url, ResponderPtr); + void getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr); + + void process(); + + private: + Easy* easyAlloc(); + void easyFree(Easy*); + + CURLM* mHandle; + + typedef std::vector<Easy*> EasyList; + EasyList mFreeEasy; + }; + + + static void get(const std::string& url, ResponderPtr); + static void getByteRange(const std::string& url, S32 offset, S32 length, ResponderPtr responder); + + static void process(); +}; + +namespace boost +{ + void intrusive_ptr_add_ref(LLCurl::Responder* p); + void intrusive_ptr_release(LLCurl::Responder* p); +}; + +#endif // LL_LLCURL_H diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp index 4ce7bc1fcd..6fc2af2cb2 100644 --- a/indra/llmessage/llpartdata.cpp +++ b/indra/llmessage/llpartdata.cpp @@ -212,6 +212,20 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp) return TRUE; } +std::ostream& operator<<(std::ostream& s, const LLPartSysData &data) +{ + s << "Flags: " << std::hex << data.mFlags; + s << " Pattern: " << std::hex << (U32) data.mPattern << "\n"; + s << "Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n"; + s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n"; + s << "Burst Rate: " << data.mBurstRate << "\n"; + s << "Burst Radius: " << data.mBurstRadius << "\n"; + s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n"; + s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n"; + s << "Angular Velocity: " << data.mAngularVelocity << "\n"; + s << "Accel: " << data.mPartAccel; + return s; +} BOOL LLPartSysData::isNullPS(const S32 block_num) { diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h index ba3bdaf9b6..662d635a08 100644 --- a/indra/llmessage/llpartdata.h +++ b/indra/llmessage/llpartdata.h @@ -167,6 +167,9 @@ public: // a combination of multiple parameters, we // need to clamp it using a separate method instead of an accessor. void clampSourceParticleRate(); + + friend std::ostream& operator<<(std::ostream& s, const LLPartSysData &data); // Stream a + public: // Public because I'm lazy.... diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 5abc63fad0..320719072c 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -868,7 +868,7 @@ void LLPumpIO::processChain(LLChainInfo& chain) PUMP_DEBUG; if(LLIOPipe::isError(status)) { - llinfos << "Pump generated pipe error: '" + llinfos << "Pump generated pipe err: '" #if LL_DEBUG_PIPE_TYPE_IN_PUMP << typeid(*((*it).mPipe)).name() << "':'" #endif diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index 4eea7418af..bddd79367a 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -335,7 +335,7 @@ void LLTransferManager::processTransferInfo(LLMessageSystem *msgp, void **) { // Perhaps this stuff should be inside a method in LLTransferPacket? // I'm too lazy to do it now, though. - llinfos << "Playing back delayed packet " << packet_id << llendl; +// llinfos << "Playing back delayed packet " << packet_id << llendl; LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id]; // This is somewhat inefficient, but avoids us having to duplicate @@ -455,6 +455,8 @@ void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **) ttcp->deleteTransfer(ttp); return; } +#if 0 + // Spammy! const S32 LL_TRANSFER_WARN_GAP = 10; if(!ttp->gotInfo()) { @@ -468,6 +470,7 @@ void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **) << " from " << msgp->getSender() << ", got " << packet_id << " expecting " << ttp->getNextPacketID() << llendl; } +#endif return; } @@ -508,7 +511,7 @@ void LLTransferManager::processTransferPacket(LLMessageSystem *msgp, void **) { // Perhaps this stuff should be inside a method in LLTransferPacket? // I'm too lazy to do it now, though. - llinfos << "Playing back delayed packet " << packet_id << llendl; +// llinfos << "Playing back delayed packet " << packet_id << llendl; LLTransferPacket *packetp = ttp->mDelayedPacketMap[packet_id]; // This is somewhat inefficient, but avoids us having to duplicate diff --git a/indra/llmessage/lltransfertargetvfile.cpp b/indra/llmessage/lltransfertargetvfile.cpp index b8c138886a..6714185d3f 100644 --- a/indra/llmessage/lltransfertargetvfile.cpp +++ b/indra/llmessage/lltransfertargetvfile.cpp @@ -15,33 +15,8 @@ #include "llvfile.h" //static -std::list<LLTransferTargetParamsVFile*> LLTransferTargetVFile::sCallbackQueue; - -//static void LLTransferTargetVFile::updateQueue(bool shutdown) { - for(std::list<LLTransferTargetParamsVFile*>::iterator iter = sCallbackQueue.begin(); - iter != sCallbackQueue.end(); ) - { - std::list<LLTransferTargetParamsVFile*>::iterator curiter = iter++; - LLTransferTargetParamsVFile* params = *curiter; - LLVFSThread::status_t s = LLVFile::getVFSThread()->getRequestStatus(params->mHandle); - if (s == LLVFSThread::STATUS_COMPLETE || s == LLVFSThread::STATUS_EXPIRED) - { - params->mCompleteCallback( - params->mErrCode, - params->getAssetID(), - params->getAssetType(), - params->mUserDatap); - delete params; - iter = sCallbackQueue.erase(curiter); - } - else if (shutdown) - { - delete params; - iter = sCallbackQueue.erase(curiter); - } - } } @@ -50,8 +25,7 @@ LLTransferTargetParamsVFile::LLTransferTargetParamsVFile() : mAssetType(LLAssetType::AT_NONE), mCompleteCallback(NULL), mUserDatap(NULL), - mErrCode(0), - mHandle(LLVFSThread::nullHandle()) + mErrCode(0) { } @@ -166,7 +140,6 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) llwarns << "Aborting vfile transfer after asset storage shut down!" << llendl; return; } - LLVFSThread::handle_t handle = LLVFSThread::nullHandle(); // Still need to gracefully handle error conditions. S32 err_code = 0; @@ -175,11 +148,11 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) case LLTS_DONE: if (!mNeedsCreate) { - handle = LLVFile::getVFSThread()->rename( - gAssetStorage->mVFS, - mTempID, mParams.getAssetType(), - mParams.getAssetID(), mParams.getAssetType(), - LLVFSThread::AUTO_DELETE); + LLVFile file(gAssetStorage->mVFS, mTempID, mParams.getAssetType(), LLVFile::WRITE); + if (!file.rename(mParams.getAssetID(), mParams.getAssetType())) + { + llerrs << "LLTransferTargetVFile: rename failed" << llendl; + } } err_code = LL_ERR_NOERR; lldebugs << "LLTransferTargetVFile::completionCallback for " @@ -219,20 +192,9 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status) } if (mParams.mCompleteCallback) { - if (handle != LLVFSThread::nullHandle()) - { - LLTransferTargetParamsVFile* params = new LLTransferTargetParamsVFile(mParams); - params->mErrCode = err_code; - params->mHandle = handle; - sCallbackQueue.push_back(params); - } - else - { - mParams.mCompleteCallback( - err_code, - mParams.getAssetID(), - mParams.getAssetType(), - mParams.mUserDatap); - } + mParams.mCompleteCallback(err_code, + mParams.getAssetID(), + mParams.getAssetType(), + mParams.mUserDatap); } } diff --git a/indra/llmessage/lltransfertargetvfile.h b/indra/llmessage/lltransfertargetvfile.h index 57eaeca378..e9d5fa0c00 100644 --- a/indra/llmessage/lltransfertargetvfile.h +++ b/indra/llmessage/lltransfertargetvfile.h @@ -71,8 +71,6 @@ protected: BOOL mNeedsCreate; LLUUID mTempID; - - static std::list<LLTransferTargetParamsVFile*> sCallbackQueue; }; #endif // LL_LLTRANSFERTARGETFILE_H diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 48d950e377..3f9dfa08d6 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -421,6 +421,7 @@ public: void addStringFast( const char* varname, const std::string& s); // typed, checks storage space void addString( const char* varname, const std::string& s); // typed, checks storage space + TPACKETID getCurrentRecvPacketID() { return mCurrentRecvPacketID; } S32 getCurrentSendTotal() const { return mCurrentSendTotal; } // This method checks for current send total and returns true if |