Merge branch 'curlthreading2' of git://github.com/AlericInglewood/SingularityViewer into curlthreading
This commit is contained in:
@@ -264,7 +264,7 @@ bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_co
|
|||||||
{
|
{
|
||||||
done = true; // request does not exist
|
done = true; // request does not exist
|
||||||
}
|
}
|
||||||
else if (req->getStatus() == STATUS_COMPLETE)
|
else if (req->getStatus() == STATUS_COMPLETE && !(req->getFlags() & FLAG_LOCKED))
|
||||||
{
|
{
|
||||||
res = true;
|
res = true;
|
||||||
if (auto_complete)
|
if (auto_complete)
|
||||||
@@ -372,9 +372,17 @@ bool LLQueuedThread::completeRequest(handle_t handle)
|
|||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
|
// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
|
||||||
#endif
|
#endif
|
||||||
mRequestHash.erase(handle);
|
if (!(req->getFlags() & FLAG_LOCKED))
|
||||||
req->deleteRequest();
|
{
|
||||||
// check();
|
mRequestHash.erase(handle);
|
||||||
|
req->deleteRequest();
|
||||||
|
// check();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Cause deletion immediately after FLAG_LOCKED is released.
|
||||||
|
req->setFlags(FLAG_AUTO_COMPLETE);
|
||||||
|
}
|
||||||
res = true;
|
res = true;
|
||||||
}
|
}
|
||||||
unlockData();
|
unlockData();
|
||||||
@@ -421,12 +429,44 @@ S32 LLQueuedThread::processNextRequest()
|
|||||||
if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
|
if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING))
|
||||||
{
|
{
|
||||||
req->setStatus(STATUS_ABORTED);
|
req->setStatus(STATUS_ABORTED);
|
||||||
|
// Unlock, because we can't call finishRequest() while keeping this lock:
|
||||||
|
// generateHandle() takes this lock too and is called while holding a lock
|
||||||
|
// (ie LLTextureFetchWorker::mWorkMutex) that finishRequest will lock too,
|
||||||
|
// causing a dead lock.
|
||||||
|
// Although a complete rewrite of LLQueuedThread is in order because it's
|
||||||
|
// far from robust the way it handles it's locking; the following rationale
|
||||||
|
// at least makes plausible that releasing the lock here SHOULD work if
|
||||||
|
// the original coder didn't completely fuck up: if before the QueuedRequest
|
||||||
|
// req was only accessed while keeping the lock, then it still should
|
||||||
|
// never happen that another thread is waiting for this lock in order to
|
||||||
|
// access the QueuedRequest: a few lines lower we delete it.
|
||||||
|
// In other words, if directly after releasing this lock another thread
|
||||||
|
// would access req, then that can only happen by finding it again in
|
||||||
|
// either mRequestQueue or mRequestHash. We already deleted it from the
|
||||||
|
// first, so this access would have to happen by finding it in mRequestHash.
|
||||||
|
// Such access happens in the following functions:
|
||||||
|
// 1) LLQueuedThread::shutdown -- but it does that anyway, as it doesn't use any locking.
|
||||||
|
// 2) LLQueuedThread::generateHandle -- might skip our handle while before it would block until we deleted it. Skipping it is actually better.
|
||||||
|
// 3) LLQueuedThread::waitForResult -- this now doesn't touch the req when it has the flag FLAG_LOCKED set.
|
||||||
|
// 4) LLQueuedThread::getRequest -- whereever this is used, FLAG_LOCKED is tested before using the req.
|
||||||
|
// 5) LLQueuedThread::getRequestStatus -- this is a read-only operation on the status, which should never be changed from finishRequest().
|
||||||
|
// 6) LLQueuedThread::abortRequest -- it doesn't seem to hurt to add flags (if this happens at all), while calling finishRequest().
|
||||||
|
// 7) LLQueuedThread::setFlags -- same.
|
||||||
|
// 8) LLQueuedThread::setPriority -- doesn't access req with status STATUS_ABORTED, STATUS_COMPLETE or STATUS_INPROGRESS.
|
||||||
|
// 9) LLQueuedThread::completeRequest -- now sets FLAG_AUTO_COMPLETE instead of deleting the req, if FLAG_LOCKED is set, so that deletion happens here when finishRequest returns.
|
||||||
|
req->setFlags(FLAG_LOCKED);
|
||||||
|
unlockData();
|
||||||
req->finishRequest(false);
|
req->finishRequest(false);
|
||||||
if (req->getFlags() & FLAG_AUTO_COMPLETE)
|
lockData();
|
||||||
|
req->resetFlags(FLAG_LOCKED);
|
||||||
|
if ((req->getFlags() & FLAG_AUTO_COMPLETE))
|
||||||
{
|
{
|
||||||
|
req->resetFlags(FLAG_AUTO_COMPLETE);
|
||||||
mRequestHash.erase(req);
|
mRequestHash.erase(req);
|
||||||
req->deleteRequest();
|
|
||||||
// check();
|
// check();
|
||||||
|
unlockData();
|
||||||
|
req->deleteRequest();
|
||||||
|
lockData();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -453,14 +493,23 @@ S32 LLQueuedThread::processNextRequest()
|
|||||||
{
|
{
|
||||||
lockData();
|
lockData();
|
||||||
req->setStatus(STATUS_COMPLETE);
|
req->setStatus(STATUS_COMPLETE);
|
||||||
req->finishRequest(true);
|
req->setFlags(FLAG_LOCKED);
|
||||||
if (req->getFlags() & FLAG_AUTO_COMPLETE)
|
|
||||||
{
|
|
||||||
mRequestHash.erase(req);
|
|
||||||
req->deleteRequest();
|
|
||||||
// check();
|
|
||||||
}
|
|
||||||
unlockData();
|
unlockData();
|
||||||
|
req->finishRequest(true);
|
||||||
|
if ((req->getFlags() & FLAG_AUTO_COMPLETE))
|
||||||
|
{
|
||||||
|
lockData();
|
||||||
|
req->resetFlags(FLAG_AUTO_COMPLETE);
|
||||||
|
mRequestHash.erase(req);
|
||||||
|
// check();
|
||||||
|
req->resetFlags(FLAG_LOCKED);
|
||||||
|
unlockData();
|
||||||
|
req->deleteRequest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
req->resetFlags(FLAG_LOCKED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ public:
|
|||||||
enum flags_t {
|
enum flags_t {
|
||||||
FLAG_AUTO_COMPLETE = 1,
|
FLAG_AUTO_COMPLETE = 1,
|
||||||
FLAG_AUTO_DELETE = 2, // child-class dependent
|
FLAG_AUTO_DELETE = 2, // child-class dependent
|
||||||
FLAG_ABORT = 4
|
FLAG_ABORT = 4,
|
||||||
|
FLAG_LOCKED = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef U32 handle_t;
|
typedef U32 handle_t;
|
||||||
@@ -124,6 +125,10 @@ public:
|
|||||||
// NOTE: flags are |'d
|
// NOTE: flags are |'d
|
||||||
mFlags |= flags;
|
mFlags |= flags;
|
||||||
}
|
}
|
||||||
|
void resetFlags(U32 flags)
|
||||||
|
{
|
||||||
|
mFlags &= ~flags;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool processRequest() = 0; // Return true when request has completed
|
virtual bool processRequest() = 0; // Return true when request has completed
|
||||||
virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
|
virtual void finishRequest(bool completed); // Always called from thread after request has completed or aborted
|
||||||
|
|||||||
@@ -226,7 +226,8 @@ LLWorkerClass::~LLWorkerClass()
|
|||||||
llerrs << "LLWorkerClass destroyed with stale work handle" << llendl;
|
llerrs << "LLWorkerClass destroyed with stale work handle" << llendl;
|
||||||
}
|
}
|
||||||
if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
|
if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
|
||||||
workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
|
workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE &&
|
||||||
|
!(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED))
|
||||||
{
|
{
|
||||||
llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl;
|
llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl;
|
||||||
}
|
}
|
||||||
@@ -350,14 +351,10 @@ bool LLWorkerClass::checkWork(bool aborting)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLQueuedThread::status_t status = workreq->getStatus();
|
LLQueuedThread::status_t status = workreq->getStatus();
|
||||||
if (status == LLWorkerThread::STATUS_ABORTED)
|
if (status == LLWorkerThread::STATUS_COMPLETE || status == LLWorkerThread::STATUS_ABORTED)
|
||||||
{
|
{
|
||||||
complete = true;
|
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
|
||||||
abort = true;
|
abort = status == LLWorkerThread::STATUS_ABORTED;
|
||||||
}
|
|
||||||
else if (status == LLWorkerThread::STATUS_COMPLETE)
|
|
||||||
{
|
|
||||||
complete = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,8 +67,6 @@ set(llmessage_SOURCE_FILES
|
|||||||
llsdmessage.cpp
|
llsdmessage.cpp
|
||||||
llsdmessagebuilder.cpp
|
llsdmessagebuilder.cpp
|
||||||
llsdmessagereader.cpp
|
llsdmessagereader.cpp
|
||||||
llsdrpcclient.cpp
|
|
||||||
llsdrpcserver.cpp
|
|
||||||
llservicebuilder.cpp
|
llservicebuilder.cpp
|
||||||
llservice.cpp
|
llservice.cpp
|
||||||
llstoredmessage.cpp
|
llstoredmessage.cpp
|
||||||
@@ -168,8 +166,6 @@ set(llmessage_HEADER_FILES
|
|||||||
llsdmessage.h
|
llsdmessage.h
|
||||||
llsdmessagebuilder.h
|
llsdmessagebuilder.h
|
||||||
llsdmessagereader.h
|
llsdmessagereader.h
|
||||||
llsdrpcclient.h
|
|
||||||
llsdrpcserver.h
|
|
||||||
llservice.h
|
llservice.h
|
||||||
llservicebuilder.h
|
llservicebuilder.h
|
||||||
llstoredmessage.h
|
llstoredmessage.h
|
||||||
|
|||||||
@@ -887,6 +887,8 @@ static int curl_debug_callback(CURL*, curl_infotype infotype, char* buf, size_t
|
|||||||
marker << (void*)request->get_lockobj();
|
marker << (void*)request->get_lockobj();
|
||||||
libcw_do.push_marker();
|
libcw_do.push_marker();
|
||||||
libcw_do.marker().assign(marker.str().data(), marker.str().size());
|
libcw_do.marker().assign(marker.str().data(), marker.str().size());
|
||||||
|
if (!debug::channels::dc::curlio.is_on())
|
||||||
|
debug::channels::dc::curlio.on();
|
||||||
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcw_do, dc::curlio|cond_nonewline_cf(infotype == CURLINFO_TEXT))
|
LibcwDoutScopeBegin(LIBCWD_DEBUGCHANNELS, libcw_do, dc::curlio|cond_nonewline_cf(infotype == CURLINFO_TEXT))
|
||||||
switch (infotype)
|
switch (infotype)
|
||||||
{
|
{
|
||||||
@@ -1116,7 +1118,7 @@ CurlResponderBuffer::CurlResponderBuffer()
|
|||||||
curl_easy_request_w->send_events_to(this);
|
curl_easy_request_w->send_events_to(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define llmaybeerrs lllog(LLApp::isExiting() ? LLError::LEVEL_WARN : LLError::LEVEL_ERROR, NULL, NULL, false)
|
#define llmaybeerrs lllog(LLApp::isRunning ? LLError::LEVEL_ERROR : LLError::LEVEL_WARN, NULL, NULL, false)
|
||||||
|
|
||||||
// The callbacks need to be revoked when the CurlResponderBuffer is destructed (because that is what the callbacks use).
|
// The callbacks need to be revoked when the CurlResponderBuffer is destructed (because that is what the callbacks use).
|
||||||
// The AIThreadSafeSimple<CurlResponderBuffer> is destructed first (right to left), so when we get here then the
|
// The AIThreadSafeSimple<CurlResponderBuffer> is destructed first (right to left), so when we get here then the
|
||||||
|
|||||||
@@ -1,255 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file llsdrpcclient.cpp
|
|
||||||
* @author Phoenix
|
|
||||||
* @date 2005-11-05
|
|
||||||
* @brief Implementation of the llsd client classes.
|
|
||||||
*
|
|
||||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
|
||||||
* Second Life Viewer Source Code
|
|
||||||
* Copyright (C) 2010, Linden Research, Inc.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation;
|
|
||||||
* version 2.1 of the License only.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
||||||
* $/LicenseInfo$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "linden_common.h"
|
|
||||||
#include "llsdrpcclient.h"
|
|
||||||
|
|
||||||
#include "llbufferstream.h"
|
|
||||||
#include "llfasttimer.h"
|
|
||||||
#include "llfiltersd2xmlrpc.h"
|
|
||||||
#include "llmemtype.h"
|
|
||||||
#include "llpumpio.h"
|
|
||||||
#include "llsd.h"
|
|
||||||
#include "llsdserialize.h"
|
|
||||||
#include "llurlrequest.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String constants
|
|
||||||
*/
|
|
||||||
static std::string LLSDRPC_RESPONSE_NAME("response");
|
|
||||||
static std::string LLSDRPC_FAULT_NAME("fault");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LLSDRPCResponse
|
|
||||||
*/
|
|
||||||
LLSDRPCResponse::LLSDRPCResponse() :
|
|
||||||
mIsError(false),
|
|
||||||
mIsFault(false)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
LLSDRPCResponse::~LLSDRPCResponse()
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LLSDRPCResponse::extractResponse(const LLSD& sd)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
bool rv = true;
|
|
||||||
if(sd.has(LLSDRPC_RESPONSE_NAME))
|
|
||||||
{
|
|
||||||
mReturnValue = sd[LLSDRPC_RESPONSE_NAME];
|
|
||||||
mIsFault = false;
|
|
||||||
}
|
|
||||||
else if(sd.has(LLSDRPC_FAULT_NAME))
|
|
||||||
{
|
|
||||||
mReturnValue = sd[LLSDRPC_FAULT_NAME];
|
|
||||||
mIsFault = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mReturnValue.clear();
|
|
||||||
mIsError = true;
|
|
||||||
rv = false;
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LLFastTimer::DeclareTimer FTM_SDRPC_RESPONSE("SDRPC Response");
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
LLIOPipe::EStatus LLSDRPCResponse::process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump)
|
|
||||||
{
|
|
||||||
LLFastTimer t(FTM_SDRPC_RESPONSE);
|
|
||||||
PUMP_DEBUG;
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
if(mIsError)
|
|
||||||
{
|
|
||||||
error(pump);
|
|
||||||
}
|
|
||||||
else if(mIsFault)
|
|
||||||
{
|
|
||||||
fault(pump);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
response(pump);
|
|
||||||
}
|
|
||||||
PUMP_DEBUG;
|
|
||||||
return STATUS_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LLSDRPCClient
|
|
||||||
*/
|
|
||||||
|
|
||||||
LLSDRPCClient::LLSDRPCClient() :
|
|
||||||
mState(STATE_NONE),
|
|
||||||
mQueue(EPBQ_PROCESS)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
LLSDRPCClient::~LLSDRPCClient()
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LLSDRPCClient::call(
|
|
||||||
const std::string& uri,
|
|
||||||
const std::string& method,
|
|
||||||
const LLSD& parameter,
|
|
||||||
LLSDRPCResponse* response,
|
|
||||||
EPassBackQueue queue)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
//llinfos << "RPC: " << uri << "." << method << "(" << *parameter << ")"
|
|
||||||
// << llendl;
|
|
||||||
if(method.empty() || !response)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mState = STATE_READY;
|
|
||||||
mURI.assign(uri);
|
|
||||||
std::stringstream req;
|
|
||||||
req << LLSDRPC_REQUEST_HEADER_1 << method
|
|
||||||
<< LLSDRPC_REQUEST_HEADER_2;
|
|
||||||
LLSDSerialize::toNotation(parameter, req);
|
|
||||||
req << LLSDRPC_REQUEST_FOOTER;
|
|
||||||
mRequest = req.str();
|
|
||||||
mQueue = queue;
|
|
||||||
mResponse = response;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LLSDRPCClient::call(
|
|
||||||
const std::string& uri,
|
|
||||||
const std::string& method,
|
|
||||||
const std::string& parameter,
|
|
||||||
LLSDRPCResponse* response,
|
|
||||||
EPassBackQueue queue)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
//llinfos << "RPC: " << uri << "." << method << "(" << parameter << ")"
|
|
||||||
// << llendl;
|
|
||||||
if(method.empty() || parameter.empty() || !response)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mState = STATE_READY;
|
|
||||||
mURI.assign(uri);
|
|
||||||
std::stringstream req;
|
|
||||||
req << LLSDRPC_REQUEST_HEADER_1 << method
|
|
||||||
<< LLSDRPC_REQUEST_HEADER_2 << parameter
|
|
||||||
<< LLSDRPC_REQUEST_FOOTER;
|
|
||||||
mRequest = req.str();
|
|
||||||
mQueue = queue;
|
|
||||||
mResponse = response;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_CLIENT("SDRPC Client");
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
LLIOPipe::EStatus LLSDRPCClient::process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump)
|
|
||||||
{
|
|
||||||
LLFastTimer t(FTM_PROCESS_SDRPC_CLIENT);
|
|
||||||
PUMP_DEBUG;
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_CLIENT);
|
|
||||||
if((STATE_NONE == mState) || (!pump))
|
|
||||||
{
|
|
||||||
// You should have called the call() method already.
|
|
||||||
return STATUS_PRECONDITION_NOT_MET;
|
|
||||||
}
|
|
||||||
EStatus rv = STATUS_DONE;
|
|
||||||
switch(mState)
|
|
||||||
{
|
|
||||||
case STATE_READY:
|
|
||||||
{
|
|
||||||
PUMP_DEBUG;
|
|
||||||
// lldebugs << "LLSDRPCClient::process_impl STATE_READY" << llendl;
|
|
||||||
buffer->append(
|
|
||||||
channels.out(),
|
|
||||||
(U8*)mRequest.c_str(),
|
|
||||||
mRequest.length());
|
|
||||||
context[CONTEXT_DEST_URI_SD_LABEL] = mURI;
|
|
||||||
mState = STATE_WAITING_FOR_RESPONSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STATE_WAITING_FOR_RESPONSE:
|
|
||||||
{
|
|
||||||
PUMP_DEBUG;
|
|
||||||
// The input channel has the sd response in it.
|
|
||||||
//lldebugs << "LLSDRPCClient::process_impl STATE_WAITING_FOR_RESPONSE"
|
|
||||||
// << llendl;
|
|
||||||
LLBufferStream resp(channels, buffer.get());
|
|
||||||
LLSD sd;
|
|
||||||
LLSDSerialize::fromNotation(sd, resp, buffer->count(channels.in()));
|
|
||||||
LLSDRPCResponse* response = (LLSDRPCResponse*)mResponse.get();
|
|
||||||
if (!response)
|
|
||||||
{
|
|
||||||
mState = STATE_DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
response->extractResponse(sd);
|
|
||||||
if(EPBQ_PROCESS == mQueue)
|
|
||||||
{
|
|
||||||
LLPumpIO::chain_t chain;
|
|
||||||
chain.push_back(mResponse);
|
|
||||||
pump->addChain(chain, DEFAULT_CHAIN_EXPIRY_SECS);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pump->respond(mResponse.get());
|
|
||||||
}
|
|
||||||
mState = STATE_DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case STATE_DONE:
|
|
||||||
default:
|
|
||||||
PUMP_DEBUG;
|
|
||||||
llinfos << "invalid state to process" << llendl;
|
|
||||||
rv = STATUS_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
@@ -1,329 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file llsdrpcclient.h
|
|
||||||
* @author Phoenix
|
|
||||||
* @date 2005-11-05
|
|
||||||
* @brief Implementation and helpers for structure data RPC clients.
|
|
||||||
*
|
|
||||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
|
||||||
* Second Life Viewer Source Code
|
|
||||||
* Copyright (C) 2010, Linden Research, Inc.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation;
|
|
||||||
* version 2.1 of the License only.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
||||||
* $/LicenseInfo$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LL_LLSDRPCCLIENT_H
|
|
||||||
#define LL_LLSDRPCCLIENT_H
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This file declares classes to encapsulate a basic structured data
|
|
||||||
* remote procedure client.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "llchainio.h"
|
|
||||||
#include "llfiltersd2xmlrpc.h"
|
|
||||||
#include "lliopipe.h"
|
|
||||||
#include "llurlrequest.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLSDRPCClientResponse
|
|
||||||
* @brief Abstract base class to represent a response from an SD server.
|
|
||||||
*
|
|
||||||
* This is used as a base class for callbacks generated from an
|
|
||||||
* structured data remote procedure call. The
|
|
||||||
* <code>extractResponse</code> method will deal with the llsdrpc method
|
|
||||||
* call overhead, and keep track of what to call during the next call
|
|
||||||
* into <code>process</code>. If you use this as a base class, you
|
|
||||||
* need to implement <code>response</code>, <code>fault</code>, and
|
|
||||||
* <code>error</code> to do something useful. When in those methods,
|
|
||||||
* you can parse and utilize the mReturnValue member data.
|
|
||||||
*/
|
|
||||||
class LLSDRPCResponse : public LLIOPipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLSDRPCResponse();
|
|
||||||
virtual ~LLSDRPCResponse();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This method extracts the response out of the sd passed in
|
|
||||||
*
|
|
||||||
* Any appropriate data found in the sd passed in will be
|
|
||||||
* extracted and managed by this object - not copied or cloned. It
|
|
||||||
* will still be up to the caller to delete the pointer passed in.
|
|
||||||
* @param sd The raw structured data response from the remote server.
|
|
||||||
* @return Returns true if this was able to parse the structured data.
|
|
||||||
*/
|
|
||||||
bool extractResponse(const LLSD& sd);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Method called when the response is ready.
|
|
||||||
*/
|
|
||||||
virtual bool response(LLPumpIO* pump) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Method called when a fault is generated by the remote server.
|
|
||||||
*/
|
|
||||||
virtual bool fault(LLPumpIO* pump) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Method called when there was an error
|
|
||||||
*/
|
|
||||||
virtual bool error(LLPumpIO* pump) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/* @name LLIOPipe virtual implementations
|
|
||||||
*/
|
|
||||||
//@{
|
|
||||||
/**
|
|
||||||
* @brief Process the data in buffer
|
|
||||||
*/
|
|
||||||
virtual EStatus process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
LLSD mReturnValue;
|
|
||||||
bool mIsError;
|
|
||||||
bool mIsFault;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLSDRPCClient
|
|
||||||
* @brief Client class for a structured data remote procedure call.
|
|
||||||
*
|
|
||||||
* This class helps deal with making structured data calls to a remote
|
|
||||||
* server. You can visualize the calls as:
|
|
||||||
* <code>
|
|
||||||
* response = uri.method(parameter)
|
|
||||||
* </code>
|
|
||||||
* where you pass in everything to <code>call</code> and this class
|
|
||||||
* takes care of the rest of the details.
|
|
||||||
* In typical usage, you will derive a class from this class and
|
|
||||||
* provide an API more useful for the specific application at
|
|
||||||
* hand. For example, if you were writing a service to send an instant
|
|
||||||
* message, you could create an API for it to send the messsage, and
|
|
||||||
* that class would do the work of translating it into the method and
|
|
||||||
* parameter, find the destination, and invoke <code>call</call> with
|
|
||||||
* a useful implementation of LLSDRPCResponse passed in to handle the
|
|
||||||
* response from the network.
|
|
||||||
*/
|
|
||||||
class LLSDRPCClient : public LLIOPipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLSDRPCClient();
|
|
||||||
virtual ~LLSDRPCClient();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enumeration for tracking which queue to process the
|
|
||||||
* response.
|
|
||||||
*/
|
|
||||||
enum EPassBackQueue
|
|
||||||
{
|
|
||||||
EPBQ_PROCESS,
|
|
||||||
EPBQ_CALLBACK,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Call a method on a remote LLSDRPCServer
|
|
||||||
*
|
|
||||||
* @param uri The remote object to call, eg,
|
|
||||||
* http://localhost/usher. If you are using a factory with a fixed
|
|
||||||
* url, the uri passed in will probably be ignored.
|
|
||||||
* @param method The method to call on the remote object
|
|
||||||
* @param parameter The parameter to pass into the remote
|
|
||||||
* object. It is up to the caller to delete the value passed in.
|
|
||||||
* @param response The object which gets the response.
|
|
||||||
* @param queue Specifies to call the response on the process or
|
|
||||||
* callback queue.
|
|
||||||
* @return Returns true if this object will be able to make the RPC call.
|
|
||||||
*/
|
|
||||||
bool call(
|
|
||||||
const std::string& uri,
|
|
||||||
const std::string& method,
|
|
||||||
const LLSD& parameter,
|
|
||||||
LLSDRPCResponse* response,
|
|
||||||
EPassBackQueue queue);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Call a method on a remote LLSDRPCServer
|
|
||||||
*
|
|
||||||
* @param uri The remote object to call, eg,
|
|
||||||
* http://localhost/usher. If you are using a factory with a fixed
|
|
||||||
* url, the uri passed in will probably be ignored.
|
|
||||||
* @param method The method to call on the remote object
|
|
||||||
* @param parameter The seriailized parameter to pass into the
|
|
||||||
* remote object.
|
|
||||||
* @param response The object which gets the response.
|
|
||||||
* @param queue Specifies to call the response on the process or
|
|
||||||
* callback queue.
|
|
||||||
* @return Returns true if this object will be able to make the RPC call.
|
|
||||||
*/
|
|
||||||
bool call(
|
|
||||||
const std::string& uri,
|
|
||||||
const std::string& method,
|
|
||||||
const std::string& parameter,
|
|
||||||
LLSDRPCResponse* response,
|
|
||||||
EPassBackQueue queue);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Enumeration for tracking client state.
|
|
||||||
*/
|
|
||||||
enum EState
|
|
||||||
{
|
|
||||||
STATE_NONE,
|
|
||||||
STATE_READY,
|
|
||||||
STATE_WAITING_FOR_RESPONSE,
|
|
||||||
STATE_DONE
|
|
||||||
};
|
|
||||||
|
|
||||||
/* @name LLIOPipe virtual implementations
|
|
||||||
*/
|
|
||||||
//@{
|
|
||||||
/**
|
|
||||||
* @brief Process the data in buffer
|
|
||||||
*/
|
|
||||||
virtual EStatus process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
EState mState;
|
|
||||||
std::string mURI;
|
|
||||||
std::string mRequest;
|
|
||||||
EPassBackQueue mQueue;
|
|
||||||
LLIOPipe::ptr_t mResponse;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLSDRPCClientFactory
|
|
||||||
* @brief Basic implementation for making an SD RPC client factory
|
|
||||||
*
|
|
||||||
* This class eases construction of a basic sd rpc client. Here is an
|
|
||||||
* example of it's use:
|
|
||||||
* <code>
|
|
||||||
* class LLUsefulService : public LLService { ... }
|
|
||||||
* LLService::registerCreator(
|
|
||||||
* "useful",
|
|
||||||
* LLService::creator_t(new LLSDRPCClientFactory<LLUsefulService>))
|
|
||||||
* </code>
|
|
||||||
*/
|
|
||||||
template<class Client>
|
|
||||||
class LLSDRPCClientFactory : public LLChainIOFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLSDRPCClientFactory() {}
|
|
||||||
LLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
|
|
||||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
|
||||||
{
|
|
||||||
lldebugs << "LLSDRPCClientFactory::build" << llendl;
|
|
||||||
LLURLRequest* http;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
http = new LLURLRequest(LLURLRequest::HTTP_POST);
|
|
||||||
}
|
|
||||||
catch(AICurlNoEasyHandle const& error)
|
|
||||||
{
|
|
||||||
llwarns << "Creating LLURLRequest failed: " << error.what() << llendl ;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLIOPipe::ptr_t service(new Client);
|
|
||||||
chain.push_back(service);
|
|
||||||
LLIOPipe::ptr_t http_pipe(http);
|
|
||||||
http->addHeader("Content-Type: text/llsd");
|
|
||||||
if(mURL.empty())
|
|
||||||
{
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
http->setURL(mURL);
|
|
||||||
}
|
|
||||||
chain.push_back(http_pipe);
|
|
||||||
chain.push_back(service);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
std::string mURL;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLXMLSDRPCClientFactory
|
|
||||||
* @brief Basic implementation for making an XMLRPC to SD RPC client factory
|
|
||||||
*
|
|
||||||
* This class eases construction of a basic sd rpc client which uses
|
|
||||||
* xmlrpc as a serialization grammar. Here is an example of it's use:
|
|
||||||
* <code>
|
|
||||||
* class LLUsefulService : public LLService { ... }
|
|
||||||
* LLService::registerCreator(
|
|
||||||
* "useful",
|
|
||||||
* LLService::creator_t(new LLXMLSDRPCClientFactory<LLUsefulService>))
|
|
||||||
* </code>
|
|
||||||
*/
|
|
||||||
template<class Client>
|
|
||||||
class LLXMLSDRPCClientFactory : public LLChainIOFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLXMLSDRPCClientFactory() {}
|
|
||||||
LLXMLSDRPCClientFactory(const std::string& fixed_url) : mURL(fixed_url) {}
|
|
||||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
|
||||||
{
|
|
||||||
lldebugs << "LLXMLSDRPCClientFactory::build" << llendl;
|
|
||||||
|
|
||||||
LLURLRequest* http;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
http = new LLURLRequest(LLURLRequest::HTTP_POST);
|
|
||||||
}
|
|
||||||
catch(AICurlNoEasyHandle const& error)
|
|
||||||
{
|
|
||||||
llwarns << "Creating LLURLRequest failed: " << error.what() << llendl ;
|
|
||||||
return false ;
|
|
||||||
}
|
|
||||||
LLIOPipe::ptr_t service(new Client);
|
|
||||||
chain.push_back(service);
|
|
||||||
LLIOPipe::ptr_t http_pipe(http);
|
|
||||||
http->addHeader("Content-Type: text/xml");
|
|
||||||
if(mURL.empty())
|
|
||||||
{
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
http->setURL(mURL);
|
|
||||||
}
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCRequest(NULL)));
|
|
||||||
chain.push_back(http_pipe);
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCResponse2LLSD));
|
|
||||||
chain.push_back(service);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
std::string mURL;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // LL_LLSDRPCCLIENT_H
|
|
||||||
@@ -1,347 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file llsdrpcserver.cpp
|
|
||||||
* @author Phoenix
|
|
||||||
* @date 2005-10-11
|
|
||||||
* @brief Implementation of the LLSDRPCServer and related classes.
|
|
||||||
*
|
|
||||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
|
||||||
* Second Life Viewer Source Code
|
|
||||||
* Copyright (C) 2010, Linden Research, Inc.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation;
|
|
||||||
* version 2.1 of the License only.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
||||||
* $/LicenseInfo$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "linden_common.h"
|
|
||||||
#include "llsdrpcserver.h"
|
|
||||||
|
|
||||||
#include "llbuffer.h"
|
|
||||||
#include "llbufferstream.h"
|
|
||||||
#include "llfasttimer.h"
|
|
||||||
#include "llmemtype.h"
|
|
||||||
#include "llpumpio.h"
|
|
||||||
#include "llsdserialize.h"
|
|
||||||
#include "llstl.h"
|
|
||||||
|
|
||||||
static const char FAULT_PART_1[] = "{'fault':{'code':i";
|
|
||||||
static const char FAULT_PART_2[] = ", 'description':'";
|
|
||||||
static const char FAULT_PART_3[] = "'}}";
|
|
||||||
|
|
||||||
static const char RESPONSE_PART_1[] = "{'response':";
|
|
||||||
static const char RESPONSE_PART_2[] = "}";
|
|
||||||
|
|
||||||
static const S32 FAULT_GENERIC = 1000;
|
|
||||||
static const S32 FAULT_METHOD_NOT_FOUND = 1001;
|
|
||||||
|
|
||||||
static const std::string LLSDRPC_METHOD_SD_NAME("method");
|
|
||||||
static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter");
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LLSDRPCServer
|
|
||||||
*/
|
|
||||||
LLSDRPCServer::LLSDRPCServer() :
|
|
||||||
mState(LLSDRPCServer::STATE_NONE),
|
|
||||||
mPump(NULL),
|
|
||||||
mLock(0)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
LLSDRPCServer::~LLSDRPCServer()
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
std::for_each(
|
|
||||||
mMethods.begin(),
|
|
||||||
mMethods.end(),
|
|
||||||
llcompose1(
|
|
||||||
DeletePointerFunctor<LLSDRPCMethodCallBase>(),
|
|
||||||
llselect2nd<method_map_t::value_type>()));
|
|
||||||
std::for_each(
|
|
||||||
mCallbackMethods.begin(),
|
|
||||||
mCallbackMethods.end(),
|
|
||||||
llcompose1(
|
|
||||||
DeletePointerFunctor<LLSDRPCMethodCallBase>(),
|
|
||||||
llselect2nd<method_map_t::value_type>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
ESDRPCSStatus LLSDRPCServer::deferredResponse(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data) {
|
|
||||||
// subclass should provide a sane implementation
|
|
||||||
return ESDRPCS_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LLSDRPCServer::clearLock()
|
|
||||||
{
|
|
||||||
if(mLock && mPump)
|
|
||||||
{
|
|
||||||
mPump->clearLock(mLock);
|
|
||||||
mPump = NULL;
|
|
||||||
mLock = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static LLFastTimer::DeclareTimer FTM_PROCESS_SDRPC_SERVER("SDRPC Server");
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
LLIOPipe::EStatus LLSDRPCServer::process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump)
|
|
||||||
{
|
|
||||||
LLFastTimer t(FTM_PROCESS_SDRPC_SERVER);
|
|
||||||
PUMP_DEBUG;
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
// lldebugs << "LLSDRPCServer::process_impl" << llendl;
|
|
||||||
// Once we have all the data, We need to read the sd on
|
|
||||||
// the the in channel, and respond on the out channel
|
|
||||||
if(!eos) return STATUS_BREAK;
|
|
||||||
if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
|
|
||||||
|
|
||||||
std::string method_name;
|
|
||||||
LLIOPipe::EStatus status = STATUS_DONE;
|
|
||||||
|
|
||||||
switch(mState)
|
|
||||||
{
|
|
||||||
case STATE_DEFERRED:
|
|
||||||
PUMP_DEBUG;
|
|
||||||
if(ESDRPCS_DONE != deferredResponse(channels, buffer.get()))
|
|
||||||
{
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
buffer.get(),
|
|
||||||
FAULT_GENERIC,
|
|
||||||
"deferred response failed.");
|
|
||||||
}
|
|
||||||
mState = STATE_DONE;
|
|
||||||
return STATUS_DONE;
|
|
||||||
|
|
||||||
case STATE_DONE:
|
|
||||||
// lldebugs << "STATE_DONE" << llendl;
|
|
||||||
break;
|
|
||||||
case STATE_CALLBACK:
|
|
||||||
// lldebugs << "STATE_CALLBACK" << llendl;
|
|
||||||
PUMP_DEBUG;
|
|
||||||
method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
|
|
||||||
if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
|
|
||||||
{
|
|
||||||
if(ESDRPCS_DONE != callbackMethod(
|
|
||||||
method_name,
|
|
||||||
mRequest[LLSDRPC_PARAMETER_SD_NAME],
|
|
||||||
channels,
|
|
||||||
buffer.get()))
|
|
||||||
{
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
buffer.get(),
|
|
||||||
FAULT_GENERIC,
|
|
||||||
"Callback method call failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// this should never happen, since we should not be in
|
|
||||||
// this state unless we originally found a method and
|
|
||||||
// params during the first call to process.
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
buffer.get(),
|
|
||||||
FAULT_GENERIC,
|
|
||||||
"Invalid LLSDRPC sever state - callback without method.");
|
|
||||||
}
|
|
||||||
pump->clearLock(mLock);
|
|
||||||
mLock = 0;
|
|
||||||
mState = STATE_DONE;
|
|
||||||
break;
|
|
||||||
case STATE_NONE:
|
|
||||||
// lldebugs << "STATE_NONE" << llendl;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// First time we got here - process the SD request, and call
|
|
||||||
// the method.
|
|
||||||
PUMP_DEBUG;
|
|
||||||
LLBufferStream istr(channels, buffer.get());
|
|
||||||
mRequest.clear();
|
|
||||||
LLSDSerialize::fromNotation(
|
|
||||||
mRequest,
|
|
||||||
istr,
|
|
||||||
buffer->count(channels.in()));
|
|
||||||
|
|
||||||
// { 'method':'...', 'parameter': ... }
|
|
||||||
method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
|
|
||||||
if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
|
|
||||||
{
|
|
||||||
ESDRPCSStatus rv = callMethod(
|
|
||||||
method_name,
|
|
||||||
mRequest[LLSDRPC_PARAMETER_SD_NAME],
|
|
||||||
channels,
|
|
||||||
buffer.get());
|
|
||||||
switch(rv)
|
|
||||||
{
|
|
||||||
case ESDRPCS_DEFERRED:
|
|
||||||
mPump = pump;
|
|
||||||
mLock = pump->setLock();
|
|
||||||
mState = STATE_DEFERRED;
|
|
||||||
status = STATUS_BREAK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESDRPCS_CALLBACK:
|
|
||||||
{
|
|
||||||
mState = STATE_CALLBACK;
|
|
||||||
LLPumpIO::LLLinkInfo link;
|
|
||||||
link.mPipe = LLIOPipe::ptr_t(this);
|
|
||||||
link.mChannels = channels;
|
|
||||||
LLPumpIO::links_t links;
|
|
||||||
links.push_back(link);
|
|
||||||
pump->respond(links, buffer, context);
|
|
||||||
mLock = pump->setLock();
|
|
||||||
status = STATUS_BREAK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ESDRPCS_DONE:
|
|
||||||
mState = STATE_DONE;
|
|
||||||
break;
|
|
||||||
case ESDRPCS_ERROR:
|
|
||||||
default:
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
buffer.get(),
|
|
||||||
FAULT_GENERIC,
|
|
||||||
"Method call failed.");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// send a fault
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
buffer.get(),
|
|
||||||
FAULT_GENERIC,
|
|
||||||
"Unable to find method and parameter in request.");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PUMP_DEBUG;
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
ESDRPCSStatus LLSDRPCServer::callMethod(
|
|
||||||
const std::string& method,
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* response)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
// Try to find the method in the method table.
|
|
||||||
ESDRPCSStatus rv = ESDRPCS_DONE;
|
|
||||||
method_map_t::iterator it = mMethods.find(method);
|
|
||||||
if(it != mMethods.end())
|
|
||||||
{
|
|
||||||
rv = (*it).second->call(params, channels, response);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it = mCallbackMethods.find(method);
|
|
||||||
if(it == mCallbackMethods.end())
|
|
||||||
{
|
|
||||||
// method not found.
|
|
||||||
std::ostringstream message;
|
|
||||||
message << "rpc server unable to find method: " << method;
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
response,
|
|
||||||
FAULT_METHOD_NOT_FOUND,
|
|
||||||
message.str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// we found it in the callback methods - tell the process
|
|
||||||
// to coordinate calling on the pump callback.
|
|
||||||
return ESDRPCS_CALLBACK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// virtual
|
|
||||||
ESDRPCSStatus LLSDRPCServer::callbackMethod(
|
|
||||||
const std::string& method,
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* response)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
// Try to find the method in the callback method table.
|
|
||||||
ESDRPCSStatus rv = ESDRPCS_DONE;
|
|
||||||
method_map_t::iterator it = mCallbackMethods.find(method);
|
|
||||||
if(it != mCallbackMethods.end())
|
|
||||||
{
|
|
||||||
rv = (*it).second->call(params, channels, response);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::ostringstream message;
|
|
||||||
message << "pcserver unable to find callback method: " << method;
|
|
||||||
buildFault(
|
|
||||||
channels,
|
|
||||||
response,
|
|
||||||
FAULT_METHOD_NOT_FOUND,
|
|
||||||
message.str());
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void LLSDRPCServer::buildFault(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data,
|
|
||||||
S32 code,
|
|
||||||
const std::string& msg)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
LLBufferStream ostr(channels, data);
|
|
||||||
ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
|
|
||||||
llinfos << "LLSDRPCServer::buildFault: " << code << ", " << msg << llendl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
void LLSDRPCServer::buildResponse(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data,
|
|
||||||
const LLSD& response)
|
|
||||||
{
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
|
|
||||||
LLBufferStream ostr(channels, data);
|
|
||||||
ostr << RESPONSE_PART_1;
|
|
||||||
LLSDSerialize::toNotation(response, ostr);
|
|
||||||
ostr << RESPONSE_PART_2;
|
|
||||||
#if LL_DEBUG
|
|
||||||
std::ostringstream debug_ostr;
|
|
||||||
debug_ostr << "LLSDRPCServer::buildResponse: ";
|
|
||||||
LLSDSerialize::toNotation(response, debug_ostr);
|
|
||||||
llinfos << debug_ostr.str() << llendl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
@@ -1,360 +0,0 @@
|
|||||||
/**
|
|
||||||
* @file llsdrpcserver.h
|
|
||||||
* @author Phoenix
|
|
||||||
* @date 2005-10-11
|
|
||||||
* @brief Declaration of the structured data remote procedure call server.
|
|
||||||
*
|
|
||||||
* $LicenseInfo:firstyear=2005&license=viewerlgpl$
|
|
||||||
* Second Life Viewer Source Code
|
|
||||||
* Copyright (C) 2010, Linden Research, Inc.
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation;
|
|
||||||
* version 2.1 of the License only.
|
|
||||||
*
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*
|
|
||||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
||||||
* $/LicenseInfo$
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LL_LLSDRPCSERVER_H
|
|
||||||
#define LL_LLSDRPCSERVER_H
|
|
||||||
|
|
||||||
/**
|
|
||||||
* I've set this up to be pretty easy to use when you want to make a
|
|
||||||
* structured data rpc server which responds to methods by
|
|
||||||
* name. Derive a class from the LLSDRPCServer, and during
|
|
||||||
* construction (or initialization if you have the luxury) map method
|
|
||||||
* names to pointers to member functions. This will look a lot like:
|
|
||||||
*
|
|
||||||
* <code>
|
|
||||||
* class LLMessageAgents : public LLSDRPCServer {<br>
|
|
||||||
* public:<br>
|
|
||||||
* typedef LLSDRPCServer<LLUsher> mem_fn_t;<br>
|
|
||||||
* LLMessageAgents() {<br>
|
|
||||||
* mMethods["message"] = new mem_fn_t(this, &LLMessageAgents::rpc_IM);<br>
|
|
||||||
* mMethods["alert"] = new mem_fn_t(this, &LLMessageAgents::rpc_Alrt);<br>
|
|
||||||
* }<br>
|
|
||||||
* protected:<br>
|
|
||||||
* rpc_IM(const LLSD& params,
|
|
||||||
* const LLChannelDescriptors& channels,
|
|
||||||
* LLBufferArray* data)
|
|
||||||
* {...}<br>
|
|
||||||
* rpc_Alert(const LLSD& params,
|
|
||||||
* const LLChannelDescriptors& channels,
|
|
||||||
* LLBufferArray* data)
|
|
||||||
* {...}<br>
|
|
||||||
* };<br>
|
|
||||||
* </code>
|
|
||||||
*
|
|
||||||
* The params are an array where each element in the array is a single
|
|
||||||
* parameter in the call.
|
|
||||||
*
|
|
||||||
* It is up to you to pack a valid serialized llsd response into the
|
|
||||||
* data object passed into the method, but you can use the helper
|
|
||||||
* methods below to help.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include "lliopipe.h"
|
|
||||||
#include "lliohttpserver.h"
|
|
||||||
#include "llfiltersd2xmlrpc.h"
|
|
||||||
|
|
||||||
class LLSD;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enumeration for specifying server method call status. This
|
|
||||||
* enumeration controls how the server class will manage the pump
|
|
||||||
* process/callback mechanism.
|
|
||||||
*/
|
|
||||||
enum ESDRPCSStatus
|
|
||||||
{
|
|
||||||
// The call went ok, but the response is not yet ready. The
|
|
||||||
// method will arrange for the clearLock() call to be made at
|
|
||||||
// a later date, after which, once the chain is being pumped
|
|
||||||
// again, deferredResponse() will be called to gather the result
|
|
||||||
ESDRPCS_DEFERRED,
|
|
||||||
|
|
||||||
// The LLSDRPCServer would like to handle the method on the
|
|
||||||
// callback queue of the pump.
|
|
||||||
ESDRPCS_CALLBACK,
|
|
||||||
|
|
||||||
// The method call finished and generated output.
|
|
||||||
ESDRPCS_DONE,
|
|
||||||
|
|
||||||
// Method failed for some unspecified reason - you should avoid
|
|
||||||
// this. A generic fault will be sent to the output.
|
|
||||||
ESDRPCS_ERROR,
|
|
||||||
|
|
||||||
ESDRPCS_COUNT,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLSDRPCMethodCallBase
|
|
||||||
* @brief Base class for calling a member function in an sd rpcserver
|
|
||||||
* implementation.
|
|
||||||
*/
|
|
||||||
class LLSDRPCMethodCallBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLSDRPCMethodCallBase() {}
|
|
||||||
virtual ~LLSDRPCMethodCallBase() {}
|
|
||||||
|
|
||||||
virtual ESDRPCSStatus call(
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* response) = 0;
|
|
||||||
protected:
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLSDRPCMethodCall
|
|
||||||
* @brief Class which implements member function calls.
|
|
||||||
*/
|
|
||||||
template<class Server>
|
|
||||||
class LLSDRPCMethodCall : public LLSDRPCMethodCallBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef ESDRPCSStatus (Server::*mem_fn)(
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data);
|
|
||||||
LLSDRPCMethodCall(Server* s, mem_fn fn) :
|
|
||||||
mServer(s),
|
|
||||||
mMemFn(fn)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
virtual ~LLSDRPCMethodCall() {}
|
|
||||||
virtual ESDRPCSStatus call(
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data)
|
|
||||||
{
|
|
||||||
return (*mServer.*mMemFn)(params, channels, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Server* mServer;
|
|
||||||
mem_fn mMemFn;
|
|
||||||
//bool (Server::*mMemFn)(const LLSD& params, LLBufferArray& data);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLSDRPCServer
|
|
||||||
* @brief Basic implementation of a structure data rpc server
|
|
||||||
*
|
|
||||||
* The rpc server is also designed to appropriately straddle the pump
|
|
||||||
* <code>process()</code> and <code>callback()</code> to specify which
|
|
||||||
* thread you want to work on when handling a method call. The
|
|
||||||
* <code>mMethods</code> methods are called from
|
|
||||||
* <code>process()</code>, while the <code>mCallbackMethods</code> are
|
|
||||||
* called when a pump is in a <code>callback()</code> cycle.
|
|
||||||
*/
|
|
||||||
class LLSDRPCServer : public LLIOPipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLSDRPCServer();
|
|
||||||
virtual ~LLSDRPCServer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* enumeration for generic fault codes
|
|
||||||
*/
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
FAULT_BAD_REQUEST = 2000,
|
|
||||||
FAULT_NO_RESPONSE = 2001,
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Call this method to return an rpc fault.
|
|
||||||
*
|
|
||||||
* @param channel The channel for output on the data buffer
|
|
||||||
* @param data buffer which will recieve the final output
|
|
||||||
* @param code The fault code
|
|
||||||
* @param msg The fault message
|
|
||||||
*/
|
|
||||||
static void buildFault(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data,
|
|
||||||
S32 code,
|
|
||||||
const std::string& msg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Call this method to build an rpc response.
|
|
||||||
*
|
|
||||||
* @param channel The channel for output on the data buffer
|
|
||||||
* @param data buffer which will recieve the final output
|
|
||||||
* @param response The return value from the method call
|
|
||||||
*/
|
|
||||||
static void buildResponse(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data,
|
|
||||||
const LLSD& response);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/* @name LLIOPipe virtual implementations
|
|
||||||
*/
|
|
||||||
//@{
|
|
||||||
/**
|
|
||||||
* @brief Process the data in buffer
|
|
||||||
*/
|
|
||||||
virtual EStatus process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enumeration to track the state of the rpc server instance
|
|
||||||
*/
|
|
||||||
enum EState
|
|
||||||
{
|
|
||||||
STATE_NONE,
|
|
||||||
STATE_CALLBACK,
|
|
||||||
STATE_DEFERRED,
|
|
||||||
STATE_DONE
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This method is called when an http post comes in.
|
|
||||||
*
|
|
||||||
* The default behavior is to look at the method name, look up the
|
|
||||||
* method in the method table, and call it. If the method is not
|
|
||||||
* found, this function will build a fault response. You can
|
|
||||||
* implement your own version of this function if you want to hard
|
|
||||||
* wire some behavior or optimize things a bit.
|
|
||||||
* @param method The method name being called
|
|
||||||
* @param params The parameters
|
|
||||||
* @param channel The channel for output on the data buffer
|
|
||||||
* @param data The http data
|
|
||||||
* @return Returns the status of the method call, done/deferred/etc
|
|
||||||
*/
|
|
||||||
virtual ESDRPCSStatus callMethod(
|
|
||||||
const std::string& method,
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This method is called when a pump callback is processed.
|
|
||||||
*
|
|
||||||
* The default behavior is to look at the method name, look up the
|
|
||||||
* method in the callback method table, and call it. If the method
|
|
||||||
* is not found, this function will build a fault response. You
|
|
||||||
* can implement your own version of this function if you want to
|
|
||||||
* hard wire some behavior or optimize things a bit.
|
|
||||||
* @param method The method name being called
|
|
||||||
* @param params The parameters
|
|
||||||
* @param channel The channel for output on the data buffer
|
|
||||||
* @param data The http data
|
|
||||||
* @return Returns the status of the method call, done/deferred/etc
|
|
||||||
*/
|
|
||||||
virtual ESDRPCSStatus callbackMethod(
|
|
||||||
const std::string& method,
|
|
||||||
const LLSD& params,
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Called after a deferred service is unlocked
|
|
||||||
*
|
|
||||||
* If a method returns ESDRPCS_DEFERRED, then the service chain
|
|
||||||
* will be locked and not processed until some other system calls
|
|
||||||
* clearLock() on the service instance again. At that point,
|
|
||||||
* once the pump starts processing the chain again, this method
|
|
||||||
* will be called so the service can output the final result
|
|
||||||
* into the buffers.
|
|
||||||
*/
|
|
||||||
virtual ESDRPCSStatus deferredResponse(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
LLBufferArray* data);
|
|
||||||
|
|
||||||
// donovan put this public here 7/27/06
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief unlock a service that as ESDRPCS_DEFERRED
|
|
||||||
*/
|
|
||||||
void clearLock();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
EState mState;
|
|
||||||
LLSD mRequest;
|
|
||||||
LLPumpIO* mPump;
|
|
||||||
S32 mLock;
|
|
||||||
typedef std::map<std::string, LLSDRPCMethodCallBase*> method_map_t;
|
|
||||||
method_map_t mMethods;
|
|
||||||
method_map_t mCallbackMethods;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name Helper Templates for making LLHTTPNodes
|
|
||||||
*
|
|
||||||
* These templates help in creating nodes for handing a service from
|
|
||||||
* either SDRPC or XMLRPC, given a single implementation of LLSDRPCServer.
|
|
||||||
*
|
|
||||||
* To use it:
|
|
||||||
* \code
|
|
||||||
* class LLUsefulServer : public LLSDRPCServer { ... }
|
|
||||||
*
|
|
||||||
* LLHTTPNode& root = LLCreateHTTPWireServer(...);
|
|
||||||
* root.addNode("llsdrpc/useful", new LLSDRPCNode<LLUsefulServer>);
|
|
||||||
* root.addNode("xmlrpc/useful", new LLXMLRPCNode<LLUsefulServer>);
|
|
||||||
* \endcode
|
|
||||||
*/
|
|
||||||
//@{
|
|
||||||
|
|
||||||
template<class Server>
|
|
||||||
class LLSDRPCServerFactory : public LLChainIOFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
|
||||||
{
|
|
||||||
lldebugs << "LLXMLSDRPCServerFactory::build" << llendl;
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new Server));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Server>
|
|
||||||
class LLSDRPCNode : public LLHTTPNodeForFactory<
|
|
||||||
LLSDRPCServerFactory<Server> >
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Server>
|
|
||||||
class LLXMLRPCServerFactory : public LLChainIOFactory
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
|
|
||||||
{
|
|
||||||
lldebugs << "LLXMLSDRPCServerFactory::build" << llendl;
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterXMLRPCRequest2LLSD));
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new Server));
|
|
||||||
chain.push_back(LLIOPipe::ptr_t(new LLFilterSD2XMLRPCResponse));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Server>
|
|
||||||
class LLXMLRPCNode : public LLHTTPNodeForFactory<
|
|
||||||
LLXMLRPCServerFactory<Server> >
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
//@}
|
|
||||||
|
|
||||||
#endif // LL_LLSDRPCSERVER_H
|
|
||||||
@@ -52,7 +52,6 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;
|
|||||||
/**
|
/**
|
||||||
* String constants
|
* String constants
|
||||||
*/
|
*/
|
||||||
const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri");
|
|
||||||
const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
|
const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");
|
||||||
|
|
||||||
|
|
||||||
@@ -715,42 +714,6 @@ static size_t headerCallback(char* header_line, size_t size, size_t nmemb, void*
|
|||||||
return header_len;
|
return header_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLFastTimer::DeclareTimer FTM_PROCESS_URL_EXTRACTOR("URL Extractor");
|
|
||||||
/**
|
|
||||||
* LLContextURLExtractor
|
|
||||||
*/
|
|
||||||
// virtual
|
|
||||||
LLIOPipe::EStatus LLContextURLExtractor::process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump)
|
|
||||||
{
|
|
||||||
LLFastTimer t(FTM_PROCESS_URL_EXTRACTOR);
|
|
||||||
PUMP_DEBUG;
|
|
||||||
LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);
|
|
||||||
// The destination host is in the context.
|
|
||||||
if(context.isUndefined() || !mRequest)
|
|
||||||
{
|
|
||||||
return STATUS_PRECONDITION_NOT_MET;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy in to out, since this just extract the URL and does not
|
|
||||||
// actually change the data.
|
|
||||||
LLChangeChannel change(channels.in(), channels.out());
|
|
||||||
std::for_each(buffer->beginSegment(), buffer->endSegment(), change);
|
|
||||||
|
|
||||||
// find the context url
|
|
||||||
if(context.has(CONTEXT_DEST_URI_SD_LABEL))
|
|
||||||
{
|
|
||||||
mRequest->setURL(context[CONTEXT_DEST_URI_SD_LABEL].asString());
|
|
||||||
return STATUS_DONE;
|
|
||||||
}
|
|
||||||
return STATUS_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LLURLRequestComplete
|
* LLURLRequestComplete
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -42,7 +42,6 @@
|
|||||||
|
|
||||||
|
|
||||||
extern const std::string CONTEXT_REQUEST;
|
extern const std::string CONTEXT_REQUEST;
|
||||||
extern const std::string CONTEXT_DEST_URI_SD_LABEL;
|
|
||||||
extern const std::string CONTEXT_RESPONSE;
|
extern const std::string CONTEXT_RESPONSE;
|
||||||
extern const std::string CONTEXT_TRANSFERED_BYTES;
|
extern const std::string CONTEXT_TRANSFERED_BYTES;
|
||||||
|
|
||||||
@@ -276,42 +275,6 @@ private:
|
|||||||
LLURLRequest(const LLURLRequest&);
|
LLURLRequest(const LLURLRequest&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @class LLContextURLExtractor
|
|
||||||
* @brief This class unpacks the url out of a agent usher service so
|
|
||||||
* it can be packed into a LLURLRequest object.
|
|
||||||
* @see LLIOPipe
|
|
||||||
*
|
|
||||||
* This class assumes that the context is a map that contains an entry
|
|
||||||
* named CONTEXT_DEST_URI_SD_LABEL.
|
|
||||||
*/
|
|
||||||
class LLContextURLExtractor : public LLIOPipe
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
|
|
||||||
~LLContextURLExtractor() {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/* @name LLIOPipe virtual implementations
|
|
||||||
*/
|
|
||||||
//@{
|
|
||||||
/**
|
|
||||||
* @brief Process the data in buffer
|
|
||||||
*/
|
|
||||||
virtual EStatus process_impl(
|
|
||||||
const LLChannelDescriptors& channels,
|
|
||||||
buffer_ptr_t& buffer,
|
|
||||||
bool& eos,
|
|
||||||
LLSD& context,
|
|
||||||
LLPumpIO* pump);
|
|
||||||
//@}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
LLURLRequest* mRequest;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class LLURLRequestComplete
|
* @class LLURLRequestComplete
|
||||||
* @brief Class which can optionally be used with an LLURLRequest to
|
* @brief Class which can optionally be used with an LLURLRequest to
|
||||||
@@ -384,11 +347,4 @@ protected:
|
|||||||
EStatus mRequestStatus;
|
EStatus mRequestStatus;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* External constants
|
|
||||||
*/
|
|
||||||
extern const std::string CONTEXT_DEST_URI_SD_LABEL;
|
|
||||||
|
|
||||||
#endif // LL_LLURLREQUEST_H
|
#endif // LL_LLURLREQUEST_H
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ BOOL LLVFile::isReadComplete()
|
|||||||
{
|
{
|
||||||
LLVFSThread::Request* req = (LLVFSThread::Request*)sVFSThread->getRequest(mHandle);
|
LLVFSThread::Request* req = (LLVFSThread::Request*)sVFSThread->getRequest(mHandle);
|
||||||
LLVFSThread::status_t status = req->getStatus();
|
LLVFSThread::status_t status = req->getStatus();
|
||||||
if (status == LLVFSThread::STATUS_COMPLETE)
|
if (status == LLVFSThread::STATUS_COMPLETE && !(req->getFlags() & LLVFSThread::FLAG_LOCKED))
|
||||||
{
|
{
|
||||||
mBytesRead = req->getBytesRead();
|
mBytesRead = req->getBytesRead();
|
||||||
mPosition += mBytesRead;
|
mPosition += mBytesRead;
|
||||||
|
|||||||
@@ -253,7 +253,9 @@ extern S32 gStartImageHeight;
|
|||||||
// local globals
|
// local globals
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifdef CWDEBUG
|
||||||
|
static bool gCurlIo;
|
||||||
|
#endif
|
||||||
|
|
||||||
static LLHost gAgentSimHost;
|
static LLHost gAgentSimHost;
|
||||||
static BOOL gSkipOptionalUpdate = FALSE;
|
static BOOL gSkipOptionalUpdate = FALSE;
|
||||||
@@ -1334,6 +1336,9 @@ bool idle_startup()
|
|||||||
|
|
||||||
llinfos << "Authenticating with " << grid_uri << llendl;
|
llinfos << "Authenticating with " << grid_uri << llendl;
|
||||||
|
|
||||||
|
// Always write curl I/O debug info for the login attempt.
|
||||||
|
Debug(gCurlIo = dc::curl.is_on() && !dc::curlio.is_on(); if (gCurlIo) dc::curlio.on());
|
||||||
|
|
||||||
// TODO if statement here to use web_login_key
|
// TODO if statement here to use web_login_key
|
||||||
// OGPX : which routine would this end up in? the LLSD or XMLRPC, or ....?
|
// OGPX : which routine would this end up in? the LLSD or XMLRPC, or ....?
|
||||||
LLUserAuth::getInstance()->authenticate(
|
LLUserAuth::getInstance()->authenticate(
|
||||||
@@ -1408,6 +1413,7 @@ bool idle_startup()
|
|||||||
LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL;
|
LL_DEBUGS("AppInit") << "downloading..." << LL_ENDL;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
Debug(if (gCurlIo) dc::curlio.off()); // Login succeeded: restore dc::curlio to original state.
|
||||||
LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
|
LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
|
||||||
progress += 0.01f;
|
progress += 0.01f;
|
||||||
set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message);
|
set_startup_status(progress, LLTrans::getString("LoginProcessingResponse"), auth_message);
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ include_directories(
|
|||||||
set(test_SOURCE_FILES
|
set(test_SOURCE_FILES
|
||||||
common.cpp
|
common.cpp
|
||||||
inventory.cpp
|
inventory.cpp
|
||||||
io.cpp
|
|
||||||
# llapp_tut.cpp # Temporarily removed until thread issues can be solved
|
# llapp_tut.cpp # Temporarily removed until thread issues can be solved
|
||||||
llbase64_tut.cpp
|
llbase64_tut.cpp
|
||||||
llblowfish_tut.cpp
|
llblowfish_tut.cpp
|
||||||
|
|||||||
1604
indra/test/io.cpp
1604
indra/test/io.cpp
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user