llsdrpcserver.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:9k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llsdrpcserver.cpp
  3.  * @author Phoenix
  4.  * @date 2005-10-11
  5.  * @brief Implementation of the LLSDRPCServer and related classes.
  6.  *
  7.  * $LicenseInfo:firstyear=2005&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2005-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #include "linden_common.h"
  35. #include "llsdrpcserver.h"
  36. #include "llbuffer.h"
  37. #include "llbufferstream.h"
  38. #include "llmemtype.h"
  39. #include "llpumpio.h"
  40. #include "llsdserialize.h"
  41. #include "llstl.h"
  42. static const char FAULT_PART_1[] = "{'fault':{'code':i";
  43. static const char FAULT_PART_2[] = ", 'description':'";
  44. static const char FAULT_PART_3[] = "'}}";
  45. static const char RESPONSE_PART_1[] = "{'response':";
  46. static const char RESPONSE_PART_2[] = "}";
  47. static const S32 FAULT_GENERIC = 1000;
  48. static const S32 FAULT_METHOD_NOT_FOUND = 1001;
  49. static const std::string LLSDRPC_METHOD_SD_NAME("method");
  50. static const std::string LLSDRPC_PARAMETER_SD_NAME("parameter");
  51. /**
  52.  * LLSDRPCServer
  53.  */
  54. LLSDRPCServer::LLSDRPCServer() :
  55. mState(LLSDRPCServer::STATE_NONE),
  56. mPump(NULL),
  57. mLock(0)
  58. {
  59. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  60. }
  61. LLSDRPCServer::~LLSDRPCServer()
  62. {
  63. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  64. std::for_each(
  65. mMethods.begin(),
  66. mMethods.end(),
  67. llcompose1(
  68. DeletePointerFunctor<LLSDRPCMethodCallBase>(),
  69. llselect2nd<method_map_t::value_type>()));
  70. std::for_each(
  71. mCallbackMethods.begin(),
  72. mCallbackMethods.end(),
  73. llcompose1(
  74. DeletePointerFunctor<LLSDRPCMethodCallBase>(),
  75. llselect2nd<method_map_t::value_type>()));
  76. }
  77. // virtual
  78. ESDRPCSStatus LLSDRPCServer::deferredResponse(
  79.         const LLChannelDescriptors& channels,
  80. LLBufferArray* data) {
  81.     // subclass should provide a sane implementation
  82.     return ESDRPCS_DONE;
  83. }
  84. void LLSDRPCServer::clearLock()
  85. {
  86. if(mLock && mPump)
  87. {
  88. mPump->clearLock(mLock);
  89. mPump = NULL;
  90. mLock = 0;
  91. }
  92. }
  93. // virtual
  94. LLIOPipe::EStatus LLSDRPCServer::process_impl(
  95. const LLChannelDescriptors& channels,
  96. buffer_ptr_t& buffer,
  97. bool& eos,
  98. LLSD& context,
  99. LLPumpIO* pump)
  100. {
  101. PUMP_DEBUG;
  102. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  103. // lldebugs << "LLSDRPCServer::process_impl" << llendl;
  104. // Once we have all the data, We need to read the sd on
  105. // the the in channel, and respond on  the out channel
  106. if(!eos) return STATUS_BREAK;
  107. if(!pump || !buffer) return STATUS_PRECONDITION_NOT_MET;
  108. std::string method_name;
  109. LLIOPipe::EStatus status = STATUS_DONE;
  110. switch(mState)
  111. {
  112. case STATE_DEFERRED:
  113. PUMP_DEBUG;
  114. if(ESDRPCS_DONE != deferredResponse(channels, buffer.get()))
  115. {
  116. buildFault(
  117. channels,
  118. buffer.get(),
  119. FAULT_GENERIC,
  120. "deferred response failed.");
  121. }
  122. mState = STATE_DONE;
  123. return STATUS_DONE;
  124. case STATE_DONE:
  125. // lldebugs << "STATE_DONE" << llendl;
  126. break;
  127. case STATE_CALLBACK:
  128. // lldebugs << "STATE_CALLBACK" << llendl;
  129. PUMP_DEBUG;
  130. method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
  131. if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
  132. {
  133. if(ESDRPCS_DONE != callbackMethod(
  134.    method_name,
  135.    mRequest[LLSDRPC_PARAMETER_SD_NAME],
  136.    channels,
  137.    buffer.get()))
  138. {
  139. buildFault(
  140. channels,
  141. buffer.get(),
  142. FAULT_GENERIC,
  143. "Callback method call failed.");
  144. }
  145. }
  146. else
  147. {
  148. // this should never happen, since we should not be in
  149. // this state unless we originally found a method and
  150. // params during the first call to process.
  151. buildFault(
  152. channels,
  153. buffer.get(),
  154. FAULT_GENERIC,
  155. "Invalid LLSDRPC sever state - callback without method.");
  156. }
  157. pump->clearLock(mLock);
  158. mLock = 0;
  159. mState = STATE_DONE;
  160. break;
  161. case STATE_NONE:
  162. // lldebugs << "STATE_NONE" << llendl;
  163. default:
  164. {
  165. // First time we got here - process the SD request, and call
  166. // the method.
  167. PUMP_DEBUG;
  168. LLBufferStream istr(channels, buffer.get());
  169. mRequest.clear();
  170. LLSDSerialize::fromNotation(
  171. mRequest,
  172. istr,
  173. buffer->count(channels.in()));
  174. // { 'method':'...', 'parameter': ... }
  175. method_name = mRequest[LLSDRPC_METHOD_SD_NAME].asString();
  176. if(!method_name.empty() && mRequest.has(LLSDRPC_PARAMETER_SD_NAME))
  177. {
  178. ESDRPCSStatus rv = callMethod(
  179. method_name,
  180. mRequest[LLSDRPC_PARAMETER_SD_NAME],
  181. channels,
  182. buffer.get());
  183. switch(rv)
  184. {
  185. case ESDRPCS_DEFERRED:
  186. mPump = pump;
  187. mLock = pump->setLock();
  188. mState = STATE_DEFERRED;
  189. status = STATUS_BREAK;
  190. break;
  191. case ESDRPCS_CALLBACK:
  192. {
  193. mState = STATE_CALLBACK;
  194. LLPumpIO::LLLinkInfo link;
  195. link.mPipe = LLIOPipe::ptr_t(this);
  196. link.mChannels = channels;
  197. LLPumpIO::links_t links;
  198. links.push_back(link);
  199. pump->respond(links, buffer, context);
  200. mLock = pump->setLock();
  201. status = STATUS_BREAK;
  202. break;
  203. }
  204. case ESDRPCS_DONE:
  205. mState = STATE_DONE;
  206. break;
  207. case ESDRPCS_ERROR:
  208. default:
  209. buildFault(
  210. channels,
  211. buffer.get(),
  212. FAULT_GENERIC,
  213. "Method call failed.");
  214. break;
  215. }
  216. }
  217. else
  218. {
  219. // send a fault
  220. buildFault(
  221. channels,
  222. buffer.get(),
  223. FAULT_GENERIC,
  224. "Unable to find method and parameter in request.");
  225. }
  226. break;
  227. }
  228. }
  229. PUMP_DEBUG;
  230. return status;
  231. }
  232. // virtual
  233. ESDRPCSStatus LLSDRPCServer::callMethod(
  234. const std::string& method,
  235. const LLSD& params,
  236. const LLChannelDescriptors& channels,
  237. LLBufferArray* response)
  238. {
  239. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  240. // Try to find the method in the method table.
  241. ESDRPCSStatus rv = ESDRPCS_DONE;
  242. method_map_t::iterator it = mMethods.find(method);
  243. if(it != mMethods.end())
  244. {
  245. rv = (*it).second->call(params, channels, response);
  246. }
  247. else
  248. {
  249. it = mCallbackMethods.find(method);
  250. if(it == mCallbackMethods.end())
  251. {
  252. // method not found.
  253. std::ostringstream message;
  254. message << "rpc server unable to find method: " << method;
  255. buildFault(
  256. channels,
  257. response,
  258. FAULT_METHOD_NOT_FOUND,
  259. message.str());
  260. }
  261. else
  262. {
  263. // we found it in the callback methods - tell the process
  264. // to coordinate calling on the pump callback.
  265. return ESDRPCS_CALLBACK;
  266. }
  267. }
  268. return rv;
  269. }
  270. // virtual
  271. ESDRPCSStatus LLSDRPCServer::callbackMethod(
  272. const std::string& method,
  273. const LLSD& params,
  274. const LLChannelDescriptors& channels,
  275. LLBufferArray* response)
  276. {
  277. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  278. // Try to find the method in the callback method table.
  279. ESDRPCSStatus rv = ESDRPCS_DONE;
  280. method_map_t::iterator it = mCallbackMethods.find(method);
  281. if(it != mCallbackMethods.end())
  282. {
  283. rv = (*it).second->call(params, channels, response);
  284. }
  285. else
  286. {
  287. std::ostringstream message;
  288. message << "pcserver unable to find callback method: " << method;
  289. buildFault(
  290. channels,
  291. response,
  292. FAULT_METHOD_NOT_FOUND,
  293. message.str());
  294. }
  295. return rv;
  296. }
  297. // static
  298. void LLSDRPCServer::buildFault(
  299. const LLChannelDescriptors& channels,
  300. LLBufferArray* data,
  301. S32 code,
  302. const std::string& msg)
  303. {
  304. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  305. LLBufferStream ostr(channels, data);
  306. ostr << FAULT_PART_1 << code << FAULT_PART_2 << msg << FAULT_PART_3;
  307. llinfos << "LLSDRPCServer::buildFault: " << code << ", " << msg << llendl;
  308. }
  309. // static
  310. void LLSDRPCServer::buildResponse(
  311. const LLChannelDescriptors& channels,
  312. LLBufferArray* data,
  313. const LLSD& response)
  314. {
  315. LLMemType m1(LLMemType::MTYPE_IO_SD_SERVER);
  316. LLBufferStream ostr(channels, data);
  317. ostr << RESPONSE_PART_1;
  318. LLSDSerialize::toNotation(response, ostr);
  319. ostr << RESPONSE_PART_2;
  320. #if LL_DEBUG
  321. std::ostringstream debug_ostr;
  322. debug_ostr << "LLSDRPCServer::buildResponse: ";
  323. LLSDSerialize::toNotation(response, debug_ostr);
  324. llinfos << debug_ostr.str() << llendl;
  325. #endif
  326. }