1 /*************************************************************************** 2 val1_server.cpp -- server for userland validator tests 3 4 copyright : (C) 2002-2007 by Ewald Arnold 5 email : ulxmlrpcpp@ewald-arnold.de 6 7 These validator functions are taken from the specs 8 on http://validator.xmlrpc.com/ and should also run from 9 their online validator website. 10 11 $Id: val1_server.cpp 1151 2009-08-12 15:12:01Z ewald-arnold $ 12 13 ***************************************************************************/ 14 15 /************************************************************************** 16 * 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU Lesser General Public License as 19 * published by the Free Software Foundation; either version 2 of the License, 20 * or (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU Lesser General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 30 * 31 ***************************************************************************/ 32 33 #include <ulxmlrpcpp/ulxmlrpcpp.h> // always first header 34 35 #include <cstdlib> 36 #include <iostream> 37 #include <cstring> 38 #include <memory> 39 40 #include <ulxmlrpcpp/ulxr_except.h> 41 #include <ulxmlrpcpp/ulxr_signature.h> 42 #include <ulxmlrpcpp/ulxr_dispatcher.h> 43 #include <ulxmlrpcpp/ulxr_http_protocol.h> 44 #include <ulxmlrpcpp/ulxr_tcpip_connection.h> 45 #include <ulxmlrpcpp/ulxr_ssl_connection.h> 46 47 #include "util.c" main(int argc,char ** argv)48 49 using namespace ulxr; 50 51 bool terminate_server = false; 52 53 MethodResponse arrayOfStructs (const MethodCall &calldata) 54 { 55 if (calldata.numParams() != 1) 56 throw ParameterException(InvalidMethodParameterError, 57 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 58 +calldata.getMethodName() + ULXR_PCHAR("\"")); 59 60 Array arr = calldata.getParam(0); 61 unsigned long sum = 0; 62 for (unsigned i = 0; i < arr.size(); ++i) 63 { 64 Struct str = arr.getItem(i); 65 Integer num = str.getMember(ULXR_PCHAR("curly")); 66 sum += num.getInteger(); 67 } 68 69 return MethodResponse (Integer(sum));; 70 } 71 72 73 MethodResponse countTheEntities (const MethodCall &calldata) 74 { 75 if (calldata.numParams() != 1) 76 throw ParameterException(InvalidMethodParameterError, 77 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 78 +calldata.getMethodName() + ULXR_PCHAR("\"")); 79 80 CppString s = RpcString(calldata.getParam(0)).getString(); 81 int leftangs = 0; 82 int rightangs = 0; 83 int ampers = 0; 84 int apos = 0; 85 int quotes = 0; 86 for (unsigned i = 0; i < s.length(); ++i) 87 { 88 switch(s[i]) 89 { 90 case ULXR_CHAR('<'): ++leftangs; 91 break; 92 93 case ULXR_CHAR('>'): ++rightangs; 94 break; 95 96 case ULXR_CHAR('&'): ++ampers; 97 break; 98 99 case ULXR_CHAR('\"'): ++quotes; 100 break; 101 102 case ULXR_CHAR('\''): ++apos; 103 break; 104 } 105 } 106 107 Struct str; 108 str.addMember(ULXR_PCHAR("ctLeftAngleBrackets"), Integer(leftangs)); 109 str.addMember(ULXR_PCHAR("ctRightAngleBrackets"), Integer(rightangs)); 110 str.addMember(ULXR_PCHAR("ctAmpersands"), Integer(ampers)); 111 str.addMember(ULXR_PCHAR("ctApostrophes"), Integer(apos)); 112 str.addMember(ULXR_PCHAR("ctQuotes"), Integer(quotes)); 113 114 return MethodResponse (str); 115 } 116 117 118 MethodResponse easyStructTest (const MethodCall &calldata) 119 { 120 if (calldata.numParams() != 1) 121 throw ParameterException(InvalidMethodParameterError, 122 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 123 +calldata.getMethodName() + ULXR_CHAR("\"")); 124 125 Struct str = Struct(calldata.getParam(0)); 126 127 int sum = 0; 128 129 Integer num = str.getMember(ULXR_CHAR("moe")); 130 sum += num.getInteger(); 131 132 num = str.getMember(ULXR_CHAR("larry")); 133 sum += num.getInteger(); 134 135 num = str.getMember(ULXR_CHAR("curly")); 136 sum += num.getInteger(); 137 138 return MethodResponse (Integer(sum)); 139 } 140 141 142 MethodResponse echoStructTest (const MethodCall &calldata) 143 { 144 if (calldata.numParams() != 1) 145 throw ParameterException(InvalidMethodParameterError, 146 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 147 +calldata.getMethodName() + ULXR_PCHAR("\"")); 148 149 Struct str = Struct(calldata.getParam(0)); 150 151 // if (str.hasMember(ULXR_CHAR("mickey")) ) 152 // { 153 // ULXR_COUT << ULXR_PCHAR("mickey ") << Base64(str.getMember(ULXR_PCHAR("mickey"))).getString() << std::endl; 154 // ULXR_COUT << ULXR_PCHAR("mickey ") << Base64(str.getMember(ULXR_PCHAR("mickey"))).getBase64() << std::endl; 155 // } 156 157 return MethodResponse (str); 158 } 159 160 161 MethodResponse manyTypesTest(const MethodCall &calldata) 162 { 163 if (calldata.numParams() != 6) 164 throw ParameterException(InvalidMethodParameterError, 165 ULXR_PCHAR("Exactly 6 parameter allowed for \"") 166 +calldata.getMethodName() + ULXR_PCHAR("\"")); 167 168 Array arr; 169 170 arr.addItem(Integer(calldata.getParam(0))); 171 arr.addItem(Boolean(calldata.getParam(1))); 172 arr.addItem(RpcString(calldata.getParam(2))); 173 arr.addItem(Double(calldata.getParam(3))); 174 arr.addItem(DateTime(calldata.getParam(4))); 175 arr.addItem(Base64(calldata.getParam(5))); 176 177 return MethodResponse (arr); 178 } 179 180 181 MethodResponse moderateSizeArrayCheck(const MethodCall &calldata) 182 { 183 if (calldata.numParams() != 1) 184 throw ParameterException(InvalidMethodParameterError, 185 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 186 +calldata.getMethodName() + ULXR_PCHAR("\"")); 187 188 Array arr = calldata.getParam(0); 189 190 if (arr.size() < 2) 191 throw ParameterException(InvalidMethodParameterError, 192 ULXR_PCHAR("Need at least 2 elements in the array parameter for \"") 193 +calldata.getMethodName() + ULXR_PCHAR("\"")); 194 195 RpcString first =RpcString(arr.getItem(0)).getString(); 196 RpcString last =RpcString(arr.getItem(arr.size()-1)).getString(); 197 198 return MethodResponse (RpcString(first.getString() + last.getString())); 199 } 200 201 202 MethodResponse nestedStructTest(const MethodCall &calldata) 203 { 204 if (calldata.numParams() != 1) 205 throw ParameterException(InvalidMethodParameterError, 206 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 207 +calldata.getMethodName() + ULXR_PCHAR("\"")); 208 209 Struct years = Struct(calldata.getParam(0)); 210 Struct months = years.getMember(ULXR_CHAR("2000")); 211 Struct days = months.getMember(ULXR_CHAR("04")); 212 Struct data = days.getMember(ULXR_CHAR("01")); 213 214 int moe = Integer(data.getMember(ULXR_CHAR("moe"))).getInteger(); 215 int larry = Integer(data.getMember(ULXR_CHAR("larry"))).getInteger(); 216 int curly = Integer(data.getMember(ULXR_CHAR("curly"))).getInteger(); 217 218 return MethodResponse (Integer(moe+larry+curly)); 219 } 220 221 222 MethodResponse simpleStructReturnTest(const MethodCall &calldata) 223 224 { 225 226 if (calldata.numParams() != 1) 227 throw ParameterException(InvalidMethodParameterError, 228 ULXR_PCHAR("Exactly 1 parameter allowed for \"") 229 +calldata.getMethodName() + ULXR_PCHAR("\"")); 230 231 int i = Integer(calldata.getParam(0)).getInteger(); 232 233 Struct str; 234 str.addMember(ULXR_CHAR("times10"), Integer(i * 10)); 235 str.addMember(ULXR_CHAR("times100"), Integer(i * 100)); 236 str.addMember(ULXR_CHAR("times1000"), Integer(i * 1000)); 237 238 return MethodResponse (str); 239 } 240 241 242 ulxr::MethodResponse shutdown (const ulxr::MethodCall &/*calldata*/) 243 { 244 ULXR_COUT << ULXR_PCHAR("got signal to shut down\n"); 245 terminate_server = true; 246 return ulxr::MethodResponse(ulxr::Boolean(true)); 247 } 248 249 250 int main(int argc, char **argv) 251 { 252 ulxr::intializeLog4J(argv[0]); 253 254 ulxr::CppString host = ULXR_PCHAR("localhost"); 255 if (argc > 1) 256 host = ULXR_GET_STRING(argv[1]); 257 258 unsigned port = 32002; 259 if (argc > 2) 260 port = ulxr_atoi(argv[2]); 261 262 bool persistent = haveOption(argc, argv, "persistent"); 263 bool chunked = haveOption(argc, argv, "chunked"); 264 bool wbxml = haveOption(argc, argv, "wbxml"); 265 bool secure = haveOption(argc, argv, "ssl"); 266 267 ulxr::CppString sec = ULXR_PCHAR("unsecured"); 268 if (secure) 269 sec = ULXR_PCHAR("secured"); 270 271 ULXR_COUT << ULXR_PCHAR("Serving ") << sec << ULXR_PCHAR(" rpc requests at ") << host << ULXR_PCHAR(":") << port << std::endl; 272 ULXR_COUT << ULXR_PCHAR("Chunked transfer: ") << chunked << std::endl; 273 ULXR_COUT << ULXR_PCHAR("WBXML: ") << wbxml << std::endl; 274 275 std::auto_ptr<ulxr::TcpIpConnection> conn; 276 #ifdef ULXR_INCLUDE_SSL_STUFF 277 if (secure) 278 { 279 ulxr::SSLConnection *ssl = new ulxr::SSLConnection (true, host, port); 280 ssl->setCryptographyData("password", "foo-cert.pem", "foo-cert.pem"); 281 conn.reset(ssl); 282 } 283 else 284 #endif 285 #ifdef _MSC_VER 286 { 287 std::auto_ptr<ulxr::TcpIpConnection> temp(new ulxr::TcpIpConnection (true, host, port)); 288 conn = temp; 289 } 290 #else 291 conn.reset(new ulxr::TcpIpConnection (true, host, port)); 292 #endif 293 294 ulxr::HttpProtocol prot(conn.get()); 295 ulxr::Dispatcher server(&prot, wbxml); 296 int res = 0; 297 298 prot.setPersistent(persistent); 299 if (persistent) 300 conn->setTcpNoDelay(true); 301 302 if (prot.isPersistent()) 303 ULXR_COUT << ULXR_PCHAR("Using persistent connections\n") ; 304 else 305 ULXR_COUT << ULXR_PCHAR("Using non-persistent connections\n") ; 306 307 prot.setChunkedTransfer(chunked); 308 309 try 310 { 311 server.addMethod(&arrayOfStructs, 312 Integer::getValueName(), 313 ULXR_PCHAR("validator1.arrayOfStructs"), 314 Array::getValueName(), 315 ULXR_PCHAR("Validator function to tot up elements in a Struct")); 316 317 server.addMethod(&countTheEntities, 318 Struct::getValueName(), 319 ULXR_PCHAR("validator1.countTheEntities"), 320 RpcString::getValueName(), 321 ULXR_PCHAR("Validator function to count some characters in a string")); 322 323 server.addMethod(&easyStructTest, 324 Integer::getValueName(), 325 ULXR_PCHAR("validator1.easyStructTest"), 326 Struct::getValueName(), 327 ULXR_PCHAR("Validator function to tot up some Struct members")); 328 329 server.addMethod(&echoStructTest, 330 Struct::getValueName(), 331 ULXR_PCHAR("validator1.echoStructTest"), 332 Struct::getValueName(), 333 ULXR_PCHAR("Validator function echoing a Struct completely back")); 334 335 server.addMethod(&manyTypesTest, 336 Array::getValueName(), 337 ULXR_PCHAR("validator1.manyTypesTest"), 338 Integer::getValueName() 339 +ULXR_PCHAR(",") + Boolean::getValueName() 340 +ULXR_PCHAR(",") + RpcString::getValueName() 341 +ULXR_PCHAR(",") + Double::getValueName() 342 +ULXR_PCHAR(",") + DateTime::getValueName() 343 +ULXR_PCHAR(",") + Base64::getValueName(), 344 ULXR_PCHAR("Validator function return all input parameters back as array")); 345 346 server.addMethod(&moderateSizeArrayCheck, 347 RpcString::getValueName(), 348 ULXR_PCHAR("validator1.moderateSizeArrayCheck"), 349 Array::getValueName(), 350 ULXR_PCHAR("Validator function returns the first + the last elements of a string array")); 351 352 server.addMethod(&nestedStructTest, 353 Integer::getValueName(), 354 ULXR_PCHAR("validator1.nestedStructTest"), 355 Struct::getValueName(), 356 ULXR_PCHAR("Validator function returns sum of nested elements")); 357 358 server.addMethod(&simpleStructReturnTest, 359 Struct::getValueName(), 360 ULXR_PCHAR("validator1.simpleStructReturnTest"), 361 Integer::getValueName(), 362 ULXR_PCHAR("Validator function returns calculation with some nested elements")); 363 364 server.addMethod(&shutdown, 365 ulxr::Signature(), 366 ULXR_PCHAR("shutdown"), 367 ulxr::Signature(), 368 ULXR_PCHAR("Shut down Worker")); 369 370 for (unsigned i = 0; terminate_server == false /* i < 100 */; ++i) 371 { 372 ULXR_COUT << ULXR_PCHAR("Run ") << i << std::endl; 373 MethodCall call = server.waitForCall(); 374 MethodResponse resp = server.dispatchCall(call); 375 if (!prot.isTransmitOnly()) 376 server.sendResponse(resp); 377 if (!prot.isPersistent()) 378 prot.close(); 379 } 380 381 if (prot.isPersistent()) 382 ULXR_COUT << ULXR_PCHAR("Used persistent connections\n") ; 383 else 384 ULXR_COUT << ULXR_PCHAR("Used non-persistent connections\n") ; 385 } 386 387 catch(XmlException& xmlex) 388 { 389 res = 1; 390 ULXR_COUT << ULXR_PCHAR("Xml Error occured: ") << ULXR_GET_STRING(xmlex.why()) << std::endl; 391 ULXR_COUT << ULXR_PCHAR(" in line ") << xmlex.getErrorLine() 392 << ULXR_PCHAR(". Reason: ") << ULXR_GET_STRING(xmlex.getErrorString()) << std::endl; 393 394 if (prot.isOpen()) 395 { 396 try{ 397 MethodResponse resp(1, xmlex.why() ); 398 if (!prot.isTransmitOnly()) 399 server.sendResponse(resp); 400 } 401 catch(...) 402 { 403 ULXR_COUT << ULXR_PCHAR("error within exception occured\n"); 404 } 405 prot.close(); 406 } 407 } 408 409 catch(Exception& ex) 410 { 411 res = 1; 412 ULXR_COUT << ULXR_PCHAR("Error occured: ") << ULXR_GET_STRING(ex.why()) << std::endl; 413 if (prot.isOpen()) 414 { 415 try{ 416 MethodResponse resp(1, ex.why() ); 417 if (!prot.isTransmitOnly()) 418 server.sendResponse(resp); 419 } 420 catch(...) 421 { 422 ULXR_COUT << ULXR_PCHAR("error within exception occured\n"); 423 } 424 prot.close(); 425 } 426 } 427 428 ULXR_COUT << ULXR_PCHAR("Terminating.\n"); 429 return res; 430 } 431