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(
00186 mRequest,
00187 istr,
00188 buffer->count(channels.in()));
00189
00190
00191 method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
00192 if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
00193 {
00194 ESDRPCSStatus rv = callMethod(
00195 method_name,
00196 mRequest[LLSDRPC_PARAMETER_SD_NAME],
00197 channels,
00198 buffer.get());
00199 switch(rv)
00200 {
00201 case ESDRPCS_DEFERRED:
00202 mPump = pump;
00203 mLock = pump->setLock();
00204 mState = STATE_DEFERRED;
00205 status = STATUS_BREAK;
00206 break;
00207
00208 case ESDRPCS_CALLBACK:
00209 {
00210 mState = STATE_CALLBACK;
00211 LLPumpIO::LLLinkInfo link;
00212 link.mPipe = LLIOPipe::ptr_t(this);
00213 link.mChannels = channels;
00214 LLPumpIO::links_t links;
00215 links.push_back(link);
00216 pump->respond(links, buffer, context);
00217 mLock = pump->setLock();
00218 status = STATUS_BREAK;
00219 break;
00220 }
00221 case ESDRPCS_DONE:
00222 mState = STATE_DONE;
00223 break;
00224 case ESDRPCS_ERROR:
00225 default:
00226 buildFault(
00227 channels,
00228 buffer.get(),
00229 FAULT_GENERIC,
00230 "Method call failed.");
00231 break;
00232 }
00233 }
00234 else
00235 {
00236
00237 buildFault(
00238 channels,
00239 buffer.get(),
00240 FAULT_GENERIC,
00241 "Unable to find method and parameter in request.");
00242 }
00243 break;
00244 }
00245 }
00246
00247 PUMP_DEBUG;
00248 return status;
00249 }
00250
00251
00252 ESDRPCSStatus LLSDRPCServer::callMethod(
00253 const std::string& method,
00254 const LLSD& params,
00255 const LLChannelDescriptors& channels,
00256 LLBufferArray* response)
00257 {
00258 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00259
00260 ESDRPCSStatus rv = ESDRPCS_DONE;
00261 method_map_t::iterator it = mMethods.find(method);
00262 if(it != mMethods.end())
00263 {
00264 rv = (*it).second->call(params, channels, response);
00265 }
00266 else
00267 {
00268 it = mCallbackMethods.find(method);
00269 if(it == mCallbackMethods.end())
00270 {
00271
00272 std::ostringstream message;
00273 message << "rpc server unable to find method: " << method;
00274 buildFault(
00275 channels,
00276 response,
00277 FAULT_METHOD_NOT_FOUND,
00278 message.str());
00279 }
00280 else
00281 {
00282
00283
00284 return ESDRPCS_CALLBACK;
00285 }
00286 }
00287 return rv;
00288 }
00289
00290
00291 ESDRPCSStatus LLSDRPCServer::callbackMethod(
00292 const std::string& method,
00293 const LLSD& params,
00294 const LLChannelDescriptors& channels,
00295 LLBufferArray* response)
00296 {
00297 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00298
00299 ESDRPCSStatus rv = ESDRPCS_DONE;
00300 method_map_t::iterator it = mCallbackMethods.find(method);
00301 if(it != mCallbackMethods.end())
00302 {
00303 rv = (*it).second->call(params, channels, response);
00304 }
00305 else
00306 {
00307 std::ostringstream message;
00308 message << "pcserver unable to find callback method: " << method;
00309 buildFault(
00310 channels,
00311 response,
00312 FAULT_METHOD_NOT_FOUND,
00313 message.str());
00314 }
00315 return rv;
00316 }
00317
00318
00319 void LLSDRPCServer::buildFault(
00320 const LLChannelDescriptors& channels,
00321 LLBufferArray* data,
00322 S32 code,
00323 const std::string& msg)
00324 {
00325 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00326 LLBufferStream ostr(channels, data);
00327 ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
00328 llinfos << "LLSDRPCServer::buildFault: " << code << ", " << msg << llendl;
00329 }
00330
00331
00332 void LLSDRPCServer::buildResponse(
00333 const LLChannelDescriptors& channels,
00334 LLBufferArray* data,
00335 const LLSD& response)
00336 {
00337 LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
00338 LLBufferStream ostr(channels, data);
00339 ostr << RESPONSE_PART_1;
00340 LLSDSerialize::toNotation(response, ostr);
00341 ostr << RESPONSE_PART_2;
00342 #if LL_DEBUG
00343 std::ostringstream debug_ostr;
00344 debug_ostr << "LLSDRPCServer::buildResponse: ";
00345 LLSDSerialize::toNotation(response, debug_ostr);
00346 llinfos << debug_ostr.str() << llendl;
00347 #endif
00348 }