summaryrefslogtreecommitdiff
path: root/indra/llmessage
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage')
-rw-r--r--indra/llmessage/llcurl.cpp343
-rw-r--r--indra/llmessage/llcurl.h118
-rw-r--r--indra/llmessage/llpartdata.cpp14
-rw-r--r--indra/llmessage/llpartdata.h3
-rw-r--r--indra/llmessage/llpumpio.cpp2
-rw-r--r--indra/llmessage/lltransfermanager.cpp7
-rw-r--r--indra/llmessage/lltransfertargetvfile.cpp58
-rw-r--r--indra/llmessage/lltransfertargetvfile.h2
-rw-r--r--indra/llmessage/message.h1
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