00001
00034 #include "linden_common.h"
00035 #include "llsdrpcserver.h"
00036
00037 #include "llbuffer.h"
00038 #include "llbufferstream.h"
00039 #include "llmemtype.h"
00040 #include "llpumpio.h"
00041 #include "llsdserialize.h"
00042 #include "llstl.h"
00043
00044 static const char FAULT_PART_1[] = "{'fault':{'code':i";
00045 static const char FAULT_PART_2[] = ", 'description':'";
00046 static const char FAULT_PART_3[] = "'}}";
00047
00048 static const char RESPONSE_PART_1[] = "{'response':";
00049 static const char RESPONSE_PART_2[] = "}";
00050
00051 static const S32 FAULT_GENERIC = 1000;
00052 static const S32 FAULT_METHOD_NOT_FOUND = 1001;
00053
00054 static const std::string LLSDRPC_METHOD_SD_NAME("method");
00055 static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter");
00056
00057
00061 LLSDRPCServer::LLSDRPCServer() :
00062 mState(LLSDRPCServer::STATE_NONE),
00063 mPump(NULL),
00064 mLock(0)
00065 {
00066 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00067 }
00068
00069 LLSDRPCServer::~LLSDRPCServer()
00070 {
00071 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00072 std::for_each(
00073 mMethods.begin(),
00074 mMethods.end(),
00075 llcompose1(
00076 DeletePointerFunctor<LLSDRPCMethodCallBase>(),
00077 llselect2nd<method_map_t::value_type>()));
00078 std::for_each(
00079 mCallbackMethods.begin(),
00080 mCallbackMethods.end(),
00081 llcompose1(
00082 DeletePointerFunctor<LLSDRPCMethodCallBase>(),
00083 llselect2nd<method_map_t::value_type>()));
00084 }
00085
00086
00087
00088 ESDRPCSStatus LLSDRPCServer::deferredResponse(
00089 const LLChannelDescriptors& channels,
00090 LLBufferArray* data) {
00091
00092 return ESDRPCS_DONE;
00093 }
00094
00095 void LLSDRPCServer::clearLock()
00096 {
00097 if(mLock && mPump)
00098 {
00099 mPump->clearLock(mLock);
00100 mPump = NULL;
00101 mLock = 0;
00102 }
00103 }
00104
00105
00106 LLIOPipe::EStatus LLSDRPCServer::process_impl(
00107 const LLChannelDescriptors& channels,
00108 buffer_ptr_t& buffer,
00109 bool& eos,
00110 LLSD& context,
00111 LLPumpIO* pump)
00112 {
00113 PUMP_DEBUG;
00114 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00115
00116
00117
00118 if(!eos) return STATUS_BREAK;
00119 if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
00120
00121 std::string method_name;
00122 LLIOPipe::EStatus status = STATUS_DONE;
00123
00124 switch(mState)
00125 {
00126 case STATE_DEFERRED:
00127 PUMP_DEBUG;
00128 if(ESDRPCS_DONE != deferredResponse(channels, buffer.get()))
00129 {
00130 buildFault(
00131 channels,
00132 buffer.get(),
00133 FAULT_GENERIC,
00134 "deferred response failed.");
00135 }
00136 mState = STATE_DONE;
00137 return STATUS_DONE;
00138
00139 case STATE_DONE:
00140
00141 break;
00142 case STATE_CALLBACK:
00143
00144 PUMP_DEBUG;
00145 method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
00146 if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
00147 {
00148 if(ESDRPCS_DONE != callbackMethod(
00149 method_name,
00150 mRequest[LLSDRPC_PARAMETER_SD_NAME],
00151 channels,
00152 buffer.get()))
00153 {
00154 buildFault(
00155 channels,
00156 buffer.get(),
00157 FAULT_GENERIC,
00158 "Callback method call failed.");
00159 }
00160 }
00161 else
00162 {
00163
00164
00165
00166 buildFault(
00167 channels,
00168 buffer.get(),
00169 FAULT_GENERIC,
00170 "Invalid LLSDRPC sever state - callback without method.");
00171 }
00172 pump->clearLock(mLock);
00173 mLock = 0;
00174 mState = STATE_DONE;
00175 break;
00176 case STATE_NONE:
00177
00178 default:
00179 {
00180
00181
00182 PUMP_DEBUG;
00183 LLBufferStream istr(channels, buffer.get());
00184 mRequest.clear();
00185 LLSDSerialize::fromNotation(mRequest, istr);
00186
00187
00188 method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
00189 if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
00190 {
00191 ESDRPCSStatus rv = callMethod(
00192 method_name,
00193 mRequest[LLSDRPC_PARAMETER_SD_NAME],
00194 channels,
00195 buffer.get());
00196 switch(rv)
00197 {
00198 case ESDRPCS_DEFERRED:
00199 mPump = pump;
00200 mLock = pump->setLock();
00201 mState = STATE_DEFERRED;
00202 status = STATUS_BREAK;
00203 break;
00204
00205 case ESDRPCS_CALLBACK:
00206 {
00207 mState = STATE_CALLBACK;
00208 LLPumpIO::LLLinkInfo link;
00209 link.mPipe = LLIOPipe::ptr_t(this);
00210 link.mChannels = channels;
00211 LLPumpIO::links_t links;
00212 links.push_back(link);
00213 pump->respond(links, buffer, context);
00214 mLock = pump->setLock();
00215 status = STATUS_BREAK;
00216 break;
00217 }
00218 case ESDRPCS_DONE:
00219 mState = STATE_DONE;
00220 break;
00221 case ESDRPCS_ERROR:
00222 default:
00223 buildFault(
00224 channels,
00225 buffer.get(),
00226 FAULT_GENERIC,
00227 "Method call failed.");
00228 break;
00229 }
00230 }
00231 else
00232 {
00233
00234 buildFault(
00235 channels,
00236 buffer.get(),
00237 FAULT_GENERIC,
00238 "Unable to find method and parameter in request.");
00239 }
00240 break;
00241 }
00242 }
00243
00244 PUMP_DEBUG;
00245 return status;
00246 }
00247
00248
00249 ESDRPCSStatus LLSDRPCServer::callMethod(
00250 const std::string& method,
00251 const LLSD& params,
00252 const LLChannelDescriptors& channels,
00253 LLBufferArray* response)
00254 {
00255 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00256
00257 ESDRPCSStatus rv = ESDRPCS_DONE;
00258 method_map_t::iterator it = mMethods.find(method);
00259 if(it != mMethods.end())
00260 {
00261 rv = (*it).second->call(params, channels, response);
00262 }
00263 else
00264 {
00265 it = mCallbackMethods.find(method);
00266 if(it == mCallbackMethods.end())
00267 {
00268
00269 std::ostringstream message;
00270 message << "rpc server unable to find method: " << method;
00271 buildFault(
00272 channels,
00273 response,
00274 FAULT_METHOD_NOT_FOUND,
00275 message.str());
00276 }
00277 else
00278 {
00279
00280
00281 return ESDRPCS_CALLBACK;
00282 }
00283 }
00284 return rv;
00285 }
00286
00287
00288 ESDRPCSStatus LLSDRPCServer::callbackMethod(
00289 const std::string& method,
00290 const LLSD& params,
00291 const LLChannelDescriptors& channels,
00292 LLBufferArray* response)
00293 {
00294 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00295
00296 ESDRPCSStatus rv = ESDRPCS_DONE;
00297 method_map_t::iterator it = mCallbackMethods.find(method);
00298 if(it != mCallbackMethods.end())
00299 {
00300 rv = (*it).second->call(params, channels, response);
00301 }
00302 else
00303 {
00304 std::ostringstream message;
00305 message << "pcserver unable to find callback method: " << method;
00306 buildFault(
00307 channels,
00308 response,
00309 FAULT_METHOD_NOT_FOUND,
00310 message.str());
00311 }
00312 return rv;
00313 }
00314
00315
00316 void LLSDRPCServer::buildFault(
00317 const LLChannelDescriptors& channels,
00318 LLBufferArray* data,
00319 S32 code,
00320 const std::string& msg)
00321 {
00322 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00323 LLBufferStream ostr(channels, data);
00324 ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
00325 llinfos << "LLSDRPCServer::buildFault: " << code << ", " << msg << llendl;
00326 }
00327
00328
00329 void LLSDRPCServer::buildResponse(
00330 const LLChannelDescriptors& channels,
00331 LLBufferArray* data,
00332 const LLSD& response)
00333 {
00334 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00335 LLBufferStream ostr(channels, data);
00336 ostr << RESPONSE_PART_1;
00337 LLSDSerialize::toNotation(response, ostr);
00338 ostr << RESPONSE_PART_2;
00339 #if LL_DEBUG
00340 std::ostringstream debug_ostr;
00341 debug_ostr << "LLSDRPCServer::buildResponse: ";
00342 LLSDSerialize::toNotation(response, debug_ostr);
00343 llinfos << debug_ostr.str() << llendl;
00344 #endif
00345 }