1 /***************************************************************************
2 http_server.cpp -- test file for an http server
3
4 copyright : (C) 2002-2007 by Ewald Arnold
5 email : ulxmlrpcpp@ewald-arnold.de
6
7 $Id: http_server.cpp 1151 2009-08-12 15:12:01Z ewald-arnold $
8
9 ***************************************************************************/
10
11 /**************************************************************************
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as
15 * published by the Free Software Foundation; either version 2 of the License,
16 * or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 ***************************************************************************/
28
29 //#define ULXR_DEBUG_OUTPUT
30 //#define ULXR_SHOW_HTTP
31
32 #include <ulxmlrpcpp/ulxmlrpcpp.h> // always first header
33
34 #include <cstdlib>
35 #include <iostream>
36 #include <ctime>
37 #include <cstring>
38 #include <cstdio>
39
40 #include <ulxmlrpcpp/ulxr_tcpip_connection.h> // first, don't move: important msvc #include bug
41 #include <ulxmlrpcpp/ulxr_http_protocol.h>
42 #include <ulxmlrpcpp/ulxr_htmlform_handler.h>
43 #include <ulxmlrpcpp/ulxr_http_server.h>
44 #include <ulxmlrpcpp/ulxr_dispatcher.h>
45 #include <ulxmlrpcpp/ulxr_except.h>
46 #include <ulxmlrpcpp/ulxr_signature.h>
47
48 #include "util.c"
49
50 #ifdef ULXR_MULTITHREADED
51
52 #ifdef __WIN32__
53 const unsigned num_threads = 10;
54 #else
55 const unsigned num_threads = 10;
56 #endif
57
58 #endif // ULXR_MULTITHREADED
59
60
61 ulxr::HttpServer *my_http_server;
62
63 ////////////////////////////////////////////////////////////////////////////////////
64 // C-style handler, do everything manually
65
66
67 class TestClass
68 {
69 public:
70 static ulxr::MethodResponse testcall (const ulxr::MethodCall &calldata);
71 static ulxr::MethodResponse getInput (const ulxr::MethodCall &calldata);
72 static ulxr::MethodResponse getAllInputs (const ulxr::MethodCall &calldata);
73 static ulxr::MethodResponse setOutput (const ulxr::MethodCall &calldata);
74 };
75
76
testcall(const ulxr::MethodCall &)77 ulxr::MethodResponse TestClass::testcall (const ulxr::MethodCall &/*calldata*/)
78 {
79 ulxr::MethodResponse resp(ulxr::Integer(654321));
80 resp.setResult(ulxr::Integer(123456));
81 return resp;
82 }
83
84
getAllInputs(const ulxr::MethodCall & calldata)85 ulxr::MethodResponse TestClass::getAllInputs (const ulxr::MethodCall &calldata)
86 {
87 ulxr::CppString s;
88 for (unsigned i = 0; i < 6; ++i)
89 {
90 bool b = 1 & ulxr::getRand();
91 if (b)
92 s += '1';
93 else
94 s += '0';
95 }
96 return ulxr::MethodResponse (ulxr::RpcString(s));
97 }
98
99
getInput(const ulxr::MethodCall & calldata)100 ulxr::MethodResponse TestClass::getInput (const ulxr::MethodCall &calldata)
101 {
102 ulxr::Integer nr = calldata.getParam(0);
103 bool b = 1 & ulxr::getRand();
104 return ulxr::MethodResponse (ulxr::Boolean(b));
105 }
106
107
setOutput(const ulxr::MethodCall & calldata)108 ulxr::MethodResponse TestClass::setOutput (const ulxr::MethodCall &calldata)
109 {
110 ulxr::Integer nr = calldata.getParam(0);
111 ulxr::Boolean state = calldata.getParam(1);
112 ULXR_COUT << ULXR_PCHAR("out ") << nr.getInteger() << ULXR_PCHAR(" ") << state.getBoolean() << ULXR_PCHAR("\n");
113 ulxr::MethodResponse resp;
114 return resp;
115 }
116
117
handle_css_c()118 std::string handle_css_c()
119 {
120 return "H1 { text-align: center; color: blue; }\n"
121 "A { color: green; }\n";
122 }
123
124
get_head_c(const std::string & title)125 std::string get_head_c(const std::string &title)
126 {
127 return std::string("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">"
128 "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=iso-8859-1\">"
129 "<title>")
130 + title
131 + std::string("</title>"
132 "<link href=\"ulxr_system.css\" rel=\"stylesheet\" type=\"text/css\">"
133 "</head><body>");
134 }
135
136
get_tail_c()137 std::string get_tail_c()
138 {
139 return "</body></html>";
140 }
141
142
handle_index_c()143 std::string handle_index_c()
144 {
145 ULXR_TRACE(ULXR_PCHAR("handle_index_c"));
146 std::string resp = get_head_c("Index") +
147 "<h1>Index</h1>"
148 "<p>This page contains information about the example http server"
149 " shipped with <a href=\"http://ulxmlrpcpp.sf.net\">ulxmlrpcpp</a>.</p>"
150 "<a href=\"general.html\">General System information<a><br />"
151 "<a href=\"special.html\">Special System information<a><br /><br />"
152 "<a href=\"/rpc-info/index.html\">Information about the built-in XML-RPC server<a><br />"
153 "<a href=\"/rpc-info/calc.html\">A simple calculator<a><br />"
154 "<a href=\"/rpc-info/elements.html\">Display all form elements<a>"
155 + get_tail_c();
156 return resp;
157 }
158
159
handle_special_c()160 std::string handle_special_c()
161 {
162 ULXR_TRACE(ULXR_PCHAR("handle_special_c"));
163 std::string resp = get_head_c("Special") +
164 "<h1>Special Information</h1>"
165 "<p>This page contains really special information.</p>"
166 "<a href=\"index.html\">Index<a><br />"
167 "<a href=\"general.html\">General System information<a>"
168 + get_tail_c();
169 return resp;
170 }
171
172
handle_general_c()173 std::string handle_general_c()
174 {
175 ULXR_TRACE(ULXR_PCHAR("handle_general_c"));
176
177 int ma;
178 int mi;
179 int pa;
180 bool deb;
181 ulxr::CppString info;
182 ulxr::getVersion (ma, mi, pa, deb, info);
183 char s_ma[40];
184 char s_mi[40];
185
186 ulxr_sprintf(s_ma, "%d", ma);
187 ulxr_sprintf(s_mi, "%d", mi);
188
189 ulxr_time_t tt = time(0);
190 std::string tm (ulxr_ctime(&tt));
191
192 std::string resp = get_head_c("General") +
193 "<h1>General Information</h1>"
194 "<p>This page contains very general information.</p>"
195 "<p>"
196 "Current time: " + tm + "<br />"
197 "Library version: " + s_ma + "." + s_mi + "<br />"
198 "</p>"
199 "<a href=\"index.html\">Index<a><br />"
200 "<a href=\"special.html\">Special System information<a>"
201 + get_tail_c();
202 return resp;
203 }
204
205
206 #ifdef ULXR_SHOW_TRACE
systemInfoHandler(ulxr::HttpProtocol * prot,const ulxr::CppString & method,const ulxr::CppString & resource,const ulxr::Cpp8BitString &)207 bool systemInfoHandler(ulxr::HttpProtocol *prot,
208 const ulxr::CppString &method,
209 const ulxr::CppString &resource,
210 const ulxr::Cpp8BitString &/*conn_data*/)
211 #else
212 bool systemInfoHandler(ulxr::HttpProtocol *prot,
213 const ulxr::CppString &/*method*/,
214 const ulxr::CppString &resource,
215 const ulxr::Cpp8BitString &/*conn_data*/)
216 #endif
217 {
218 ULXR_TRACE(ULXR_PCHAR("systemInfoHandler ") << method << " " << resource);
219
220 ulxr::CppString rsc_start = ULXR_PCHAR("/system/");
221 if (resource.substr(0, rsc_start.length()) == rsc_start)
222 {
223 ulxr::CppString target = resource.substr(rsc_start.length());
224 std::string resp;
225
226 if (target.length() == 0 || target == ULXR_PCHAR("index.html"))
227 resp = handle_index_c();
228
229 else if (target == ULXR_PCHAR("general.html"))
230 resp = handle_general_c();
231
232 else if (target == ULXR_PCHAR("special.html"))
233 resp = handle_special_c();
234
235 else if (target == ULXR_PCHAR("ulxr_system.css"))
236 resp = handle_css_c();
237
238 else
239 return false;
240
241 prot->sendResponseHeader(200, ULXR_PCHAR("OK"), ULXR_PCHAR("text/html"), resp.length());
242 prot->writeRaw(resp.data(), resp.length());
243
244 return true;
245 }
246 else
247 return false;
248 }
249
250 // C-style handler
251 ////////////////////////////////////////////////////////////////////////////////////
252
253
254 ////////////////////////////////////////////////////////////////////////////////////
255 // class-style handler, use helper class extensively
256
257 class RpcInfoHandler : public ulxr::HtmlFormHandler
258 {
259 public:
260
RpcInfoHandler(ulxr::Dispatcher * in_disp)261 RpcInfoHandler(ulxr::Dispatcher *in_disp)
262 : ulxr::HtmlFormHandler(ULXR_PCHAR("/rpc-info/"))
263 {
264 disp = in_disp;
265
266 addSubResource(ULXR_PCHAR(""), this, &RpcInfoHandler::handle_index, ULXR_PCHAR("The main index page in this subresource"));
267 addSubResource(ULXR_PCHAR("index.html"), this, &RpcInfoHandler::handle_index, ULXR_PCHAR("The main index page in this subresource"));
268 addSubResource(ULXR_PCHAR("calc.html"), this, &RpcInfoHandler::handle_calc, ULXR_PCHAR("A simple calculator"));
269 addSubResource(ULXR_PCHAR("elements.html"), this, &RpcInfoHandler::handle_elements, ULXR_PCHAR("A sample page with form elements"));
270
271 addSubResource(ULXR_PCHAR("subresources.html"), (ulxr::HtmlFormHandler*)this, &ulxr::HtmlFormHandler::handle_subresource_list, ULXR_PCHAR("Display subresources"));
272 // css already handled by parent
273 }
274
275
handle_css_file(const ulxr::HtmlFormData &,ulxr::CppString & mimetype)276 virtual ulxr::CppString handle_css_file(const ulxr::HtmlFormData &, ulxr::CppString &mimetype)
277 {
278 mimetype = ULXR_PCHAR("text/css");
279 return ULXR_PCHAR("H1 { text-align: center; color: red; }\n")
280 ULXR_PCHAR("A { color: gray; }\n");
281 }
282
283
handle_index(const ulxr::HtmlFormData & formdata,ulxr::CppString & mimetype)284 ulxr::CppString handle_index(const ulxr::HtmlFormData &formdata, ulxr::CppString &mimetype)
285 {
286 mimetype = ULXR_PCHAR("text/html");
287 if (formdata.size() != 0 && formdata.hasElement(ULXR_PCHAR("method_modifier"))) // first update rpc-server
288 for (unsigned i = 0; i < disp->numMethods(); ++i)
289 disp->getMethod(i)->setEnabled(formdata.hasElement(ULXR_PCHAR("method_enable_"), i) == true);
290
291 ULXR_TRACE(ULXR_PCHAR("handle_index"));
292 ulxr::CppString resp = getHeader(ULXR_PCHAR("Index"))
293 + ULXR_PCHAR("<h1>Index</h1>")
294 + makeAnchor(ULXR_PCHAR("subresources.html"), ULXR_PCHAR("Show all subresources of this branch"))
295 + makeLineBreak()
296 + ULXR_PCHAR("<p>The following table contains information about the available rpc methods.</p>\n");
297
298 resp += openForm(ULXR_PCHAR("rpc-controller"), ULXR_PCHAR("POST"));
299
300 resp += ULXR_PCHAR("<table border=\"3\">\n")
301 ULXR_PCHAR("<tr><td>Return type</td>")
302 ULXR_PCHAR("<td>Method name</td>")
303 ULXR_PCHAR("<td>Parameter signature</td>")
304 ULXR_PCHAR("<td>Type</td>")
305 ULXR_PCHAR("<td>Description</td>")
306 + applyTags(ULXR_PCHAR("Invoked"), ULXR_PCHAR("td"))
307 + applyTags(ULXR_PCHAR("Enabled"), ULXR_PCHAR("td"))
308 + makeSubmitButton(ULXR_PCHAR("method_modifier"), ULXR_PCHAR("Update"))
309 + ULXR_PCHAR("</td>");
310
311 ULXR_TRACE(ULXR_PCHAR("handle_index 1"));
312 for (unsigned i = 0; i < disp->numMethods(); ++i)
313 {
314 ulxr::CppString id = makeNumber(i);
315
316 const ulxr::Dispatcher::MethodCallDescriptor *meth = disp->getMethod(i);
317 resp += ULXR_PCHAR("<tr>");
318 resp += ULXR_PCHAR("<td>") + meth->getReturnValueSignature() + ULXR_PCHAR("</td>");
319 resp += ULXR_PCHAR("<td>") + meth->getMethodName() + ULXR_PCHAR("</td>");
320 resp += ULXR_PCHAR("<td>") + meth->getParameterSignature() + ULXR_PCHAR("</td>");
321
322 if (meth->getCallType() == ulxr::Dispatcher::CallSystem)
323 resp += ULXR_PCHAR("<td>system</td>");
324 else
325 resp += ULXR_PCHAR("<td>external</td>");
326
327 resp += ULXR_PCHAR("<td>") + meth->getDocumentation() + ULXR_PCHAR("</td>");
328
329 resp += ULXR_PCHAR("<td>") + makeNumber(meth->getInvoked()) + ULXR_PCHAR("</td>");
330
331 resp += ULXR_PCHAR("<td>")
332 + makeCheckBox(makeIdent(ULXR_PCHAR("method_enable_"), i), ULXR_PCHAR("on"), meth->isEnabled())
333 + ULXR_PCHAR("</td>");
334
335 resp += ULXR_PCHAR("</tr>\n");
336 }
337 resp += ULXR_PCHAR("</table>");
338 resp += closeForm();
339 resp += getTail();
340 return resp;
341 }
342
343
handle_calc(const ulxr::HtmlFormData & formdata,ulxr::CppString & mimetype)344 ulxr::CppString handle_calc(const ulxr::HtmlFormData &formdata, ulxr::CppString &mimetype)
345 {
346 mimetype = ULXR_PCHAR("text/html");
347 ulxr::CppString rhs;
348 ulxr::CppString lhs;
349 ulxr::CppString result;
350 ulxr::CppString op = ULXR_PCHAR("plus");
351
352 if ( formdata.size() != 0
353 && formdata.hasElement(ULXR_PCHAR("lhs"))
354 && formdata.hasElement(ULXR_PCHAR("rhs"))
355 && formdata.hasElement(ULXR_PCHAR("operator"))
356 )
357 {
358 int l = getLong(formdata.getElement(ULXR_PCHAR("lhs"))[0]);
359 int r = getLong(formdata.getElement(ULXR_PCHAR("rhs"))[0]);
360 int res;
361 op = formdata.getElement(ULXR_PCHAR("operator"))[0];
362 if (op == ULXR_PCHAR("plus"))
363 res = l + r;
364
365 else if (op == ULXR_PCHAR("minus"))
366 res = l - r;
367
368 else if (op == ULXR_PCHAR("mul"))
369 res = l * r;
370
371 else if (op == ULXR_PCHAR("div"))
372 {
373 if (r == 0)
374 res = 0;
375 else
376 res = l / r;
377 }
378 else
379 res = 0;
380
381 rhs = makeNumber(r);
382 lhs = makeNumber(l);
383 result = makeNumber(res);
384 }
385
386 ULXR_TRACE(ULXR_PCHAR("handle_calc"));
387 ulxr::CppString resp = getHeader(ULXR_PCHAR("Calculator"))
388 + ULXR_PCHAR("<h1>Calculator</h1>")
389 ULXR_PCHAR("<p>Enter two numbers and select an operator.</p>\n");
390
391 resp += openForm(ULXR_PCHAR("magic-calculator"), ULXR_PCHAR("POST"));
392
393 resp += makeTextField(ULXR_PCHAR("lhs"), lhs);
394
395 resp += openSelect(ULXR_PCHAR("operator"));
396 resp += makeOption(ULXR_PCHAR("+"), ULXR_PCHAR("plus"), op == ULXR_PCHAR("plus"));
397 resp += makeOption(ULXR_PCHAR("-"), ULXR_PCHAR("minus"), op == ULXR_PCHAR("minus"));
398 resp += makeOption(ULXR_PCHAR("*"), ULXR_PCHAR("mul"), op == ULXR_PCHAR("mul"));
399 resp += makeOption(ULXR_PCHAR("/"), ULXR_PCHAR("div"), op == ULXR_PCHAR("div"));
400 resp += closeSelect();
401
402 resp += makeTextField(ULXR_PCHAR("rhs"), rhs);
403
404 resp += ULXR_PCHAR(" = ");
405
406 resp += makeTextField(ULXR_PCHAR("result"), result);
407
408 resp += ULXR_PCHAR("<br /><br />");
409
410 resp += makeSubmitButton(ULXR_PCHAR("start_calc"), ULXR_PCHAR("Calculate"));
411 resp += closeForm();
412
413 resp += getTail();
414 return resp;
415 }
416
417
handle_elements(const ulxr::HtmlFormData & formdata,ulxr::CppString & mimetype)418 ulxr::CppString handle_elements(const ulxr::HtmlFormData &formdata, ulxr::CppString &mimetype)
419 {
420 mimetype = ULXR_PCHAR("text/html");
421 ULXR_TRACE(ULXR_PCHAR("handle_elements"));
422 ulxr::CppString resp = getHeader(ULXR_PCHAR("Available Form Elements"))
423 + ULXR_PCHAR("<h1>Available Form Elements</h1>");
424
425 resp += openForm(ULXR_PCHAR("testform"), ULXR_PCHAR("POST"))
426 + ULXR_PCHAR("Checkbox 1")
427 + makeCheckBox (ULXR_PCHAR("Check1"), ULXR_PCHAR("on"), true)
428 + makeLineBreak()
429
430 + ULXR_PCHAR("Checkbox 2")
431 + makeCheckBox (ULXR_PCHAR("Check2"), ULXR_PCHAR("on"), false)
432 + makeLineBreak()
433
434 + ULXR_PCHAR("<br /><br />")
435
436 + makeTextField(ULXR_PCHAR("Textfield"), ULXR_PCHAR("textdata"))
437 + makeLineBreak();
438
439 if (formdata.hasElement(ULXR_PCHAR("Textfield")))
440 {
441 resp += makeLineBreak()
442 + makeText(ULXR_PCHAR("Data from text field above:"))
443 + makeLineBreak()
444 + formdata.getElement(ULXR_PCHAR("Textfield"))[0]
445 + makeLineBreak()
446 + makeLineBreak();
447 }
448
449 resp += ULXR_PCHAR("<br /><br />")
450 + makeTextArea(ULXR_PCHAR("TextArea"), ULXR_PCHAR("text +&%= line1\nline 2\nline 3"), 40, 5)
451 + makeLineBreak();
452
453 if (formdata.hasElement(ULXR_PCHAR("TextArea")))
454 {
455 resp += makeLineBreak()
456 + makeText(ULXR_PCHAR("Data from text area above:"))
457 + makeLineBreak()
458 + formdata.getElement(ULXR_PCHAR("TextArea"))[0]
459 + makeLineBreak()
460 + makeLineBreak();
461 }
462
463 resp += ULXR_PCHAR("<br /><br />")
464
465 + openSelect(ULXR_PCHAR("Select1"), 5, true)
466 + makeOption(ULXR_PCHAR("Option 1"))
467 + makeOption(ULXR_PCHAR("Option 2"), ULXR_PCHAR("opt2"))
468 + makeOption(ULXR_PCHAR("Option 3"), ULXR_PCHAR(""), true)
469 + makeOption(ULXR_PCHAR("Option 4"), ULXR_PCHAR(""), true)
470 + closeSelect()
471
472 + makeLineBreak()
473
474 + openSelect(ULXR_PCHAR("Select2"), 1, false)
475 + makeOption(ULXR_PCHAR("Option 21"))
476 + makeOption(ULXR_PCHAR("Option 22"), ULXR_PCHAR("opt2"))
477 + makeOption(ULXR_PCHAR("Option 23"), ULXR_PCHAR(""), true)
478 + makeOption(ULXR_PCHAR("Option 24"), ULXR_PCHAR(""), true)
479 + closeSelect()
480
481 + ULXR_PCHAR("<br /><br />")
482
483 + makeRadioButton(ULXR_PCHAR("radio1"), ULXR_PCHAR("val1")) + ULXR_PCHAR("Radio 1a") + makeLineBreak()
484 + makeRadioButton(ULXR_PCHAR("radio1"), ULXR_PCHAR("val2"), true) + ULXR_PCHAR("Radio 1b") + makeLineBreak()
485 + makeRadioButton(ULXR_PCHAR("radio2"), ULXR_PCHAR("val3"), true) + ULXR_PCHAR("Radio 3") + makeLineBreak()
486
487 + makeLineBreak()
488
489 + makeSubmitButton(ULXR_PCHAR("submit"), ULXR_PCHAR("Do Submit"))
490 + makeResetButton(ULXR_PCHAR("reset"), ULXR_PCHAR("Do Reset"))
491
492 + closeForm()
493
494 + getTail();
495
496 return resp;
497 }
498
499
500 private:
501 ulxr::Dispatcher *disp;
502 };
503
504 // class-style handler
505 ////////////////////////////////////////////////////////////////////////////////////
506
507
testcall(const ulxr::MethodCall & calldata)508 ulxr::MethodResponse testcall (const ulxr::MethodCall &calldata)
509 {
510 ulxr::Integer i = calldata.getParam(0);
511 ulxr::Integer i2 = calldata.getParam(1);
512
513 ulxr::Struct st;
514 st.addMember(ULXR_PCHAR("before"), i);
515 st.addMember(ULXR_PCHAR("sum"), ulxr::Integer(i.getInteger()+i2.getInteger()));
516 st.addMember(ULXR_PCHAR("difference"), ulxr::Integer(i.getInteger()-i2.getInteger()));
517
518 return ulxr::MethodResponse (st);
519 }
520
521
numThreads(const ulxr::MethodCall &)522 ulxr::MethodResponse numThreads (const ulxr::MethodCall &/*calldata*/)
523 {
524 #ifdef ULXR_MULTITHREADED
525 return ulxr::MethodResponse(ulxr::Integer(my_http_server->numThreads()));
526 #else
527 return ulxr::MethodResponse(ulxr::Integer(1));
528 #endif
529 }
530
531
shutdown(const ulxr::MethodCall &)532 ulxr::MethodResponse shutdown (const ulxr::MethodCall &/*calldata*/)
533 {
534 ULXR_COUT << ULXR_PCHAR("got signal to shut down\n");
535 my_http_server->requestTermination();
536 return ulxr::MethodResponse(ulxr::Boolean(true));
537 }
538
539
main(int argc,char ** argv)540 int main(int argc, char **argv)
541 {
542 int ret = 0;
543 try
544 {
545 ulxr::intializeLog4J(argv[0]);
546 ulxr::getLogger4J()->send(ULXR_PCHAR("DEBUG"),
547 ULXR_PCHAR("server started"),
548 ULXR_GET_STRING(__FILE__),
549 __LINE__);
550
551 ulxr::CppString host = ULXR_PCHAR("localhost");
552 if (argc > 1)
553 host = ULXR_GET_STRING(argv[1]);
554
555 unsigned port = 32001;
556 if (argc > 2)
557 port = ulxr_atoi(argv[2]);
558
559 bool auth = haveOption(argc, argv, "auth");
560 bool wbxml = haveOption(argc, argv, "wbxml");
561 bool chunked = haveOption(argc, argv, "chunked");
562 bool shutme = haveOption(argc, argv, "shutdown");
563
564 ulxr::TcpIpConnection conn (true, host, port);
565 conn.setConnectionTimeout(conn.getTimeout(), 60 * 60);
566 ulxr::HttpProtocol prot(&conn);
567 prot.setChunkedTransfer(chunked);
568 #ifdef ULXR_MULTITHREADED
569 ulxr::HttpServer http_server (&prot, num_threads, wbxml);
570 #else
571 ulxr::HttpServer http_server (&prot, wbxml);
572 #endif
573 my_http_server = &http_server;
574 http_server.addHttpHandler(ULXR_PCHAR("get"), ulxr::make_methodhandler(&systemInfoHandler));
575
576 ulxr::Dispatcher rpc_server(0, wbxml);
577
578 RpcInfoHandler rpcinfo(&rpc_server);
579 http_server.addHttpHandler(ULXR_PCHAR("get"), ulxr::make_methodhandler(rpcinfo, &RpcInfoHandler::handler));
580 http_server.addHttpHandler(ULXR_PCHAR("post"), ulxr::make_methodhandler(rpcinfo, &RpcInfoHandler::handler));
581
582 if (auth)
583 {
584 http_server.addRealm(ULXR_CHAR("/"), ULXR_CHAR("http-root-resource"));
585 http_server.addAuthentication(ULXR_CHAR("ali-baba"),
586 ULXR_CHAR("open-sesame"),
587 ULXR_CHAR("http-root-resource"));
588
589 http_server.addRealm(ULXR_CHAR("/RPC2"), ULXR_CHAR("rpc2-resource"));
590 http_server.addAuthentication(ULXR_CHAR("ali-baba-rpc"),
591 ULXR_CHAR("open-sesame-rpc"),
592 ULXR_CHAR("rpc2-resource"));
593 }
594
595 ulxr::CppString xs = conn.getErrorString(10035);
596
597 #ifdef _WIN32
598 ulxr::CppString root_dir = ULXR_PCHAR("x:\\public_html");
599 #else
600 ulxr::CppString root_dir = ULXR_PCHAR("/home/ea/public_html");
601 #endif
602 ULXR_COUT << ULXR_PCHAR("Server root directory is: ") << root_dir << std::endl;
603 ULXR_COUT << ULXR_PCHAR("Accepting http requests at ") << host << ULXR_PCHAR(":") << port << std::endl;
604 ULXR_COUT << ULXR_PCHAR("Please point your browser to \n http://")
605 << host << ULXR_PCHAR(":") << port << ULXR_PCHAR("/system/")
606 << ULXR_PCHAR("\nor to \n http://")
607 << host << ULXR_PCHAR(":") << port << ULXR_PCHAR("/rpc-info/")<< std::endl
608 << ULXR_PCHAR("username is \"ali-baba\" and password is \"open-sesame\"") << std::endl;
609 ULXR_COUT << ULXR_PCHAR("WBXML: ") << wbxml << std::endl;
610 ULXR_COUT << ULXR_PCHAR("Chunked transfer: ") << chunked << std::endl;
611
612 http_server.setHttpRoot(root_dir);
613
614 rpc_server.addMethod(ulxr::make_method(TestClass::getInput),
615 ulxr::Signature() << ulxr::Boolean(),
616 ULXR_PCHAR("getInput"),
617 ulxr::Signature()<< ulxr::Integer(),
618 ULXR_PCHAR("get input state"));
619
620 rpc_server.addMethod(ulxr::make_method(TestClass::getAllInputs),
621 ulxr::Signature() << ulxr::RpcString(),
622 ULXR_PCHAR("getAllInputs"),
623 ulxr::Signature(),
624 ULXR_PCHAR("get all input states"));
625
626 rpc_server.addMethod(ulxr::make_method(TestClass::setOutput),
627 ulxr::Signature(),
628 ULXR_PCHAR("setOutput"),
629 ulxr::Signature() << ulxr::Integer()
630 << ulxr::Boolean(),
631 ULXR_PCHAR("set output state"));
632
633 rpc_server.addMethod(&testcall,
634 ulxr::RpcString(),
635 ULXR_PCHAR("qtnns.getVersion"),
636 ulxr::Void(),
637 ULXR_PCHAR("Returns the Version of the core."));
638
639 rpc_server.addMethod(&testcall,
640 ulxr::Struct::getValueName(),
641 ULXR_CHAR("testcall"),
642 ulxr::Integer::getValueName() + ULXR_CHAR(",") + ulxr::Integer::getValueName(),
643 ULXR_CHAR("Testcase with a c-function"));
644
645 rpc_server.addMethod(ulxr::make_method(&shutdown),
646 ulxr::Signature(),
647 ULXR_PCHAR("shutdown"),
648 ulxr::Signature(),
649 ULXR_PCHAR("Shut down Worker"));
650
651 rpc_server.addMethod(ulxr::make_method(&numThreads),
652 ulxr::Signature(ulxr::Integer()),
653 ULXR_PCHAR("numthreads"),
654 ulxr::Signature(),
655 ULXR_PCHAR("Returns number of installed threads at startup"));
656
657 http_server.setRpcDispatcher(&rpc_server);
658
659 // run forever...
660 unsigned started = http_server.runPicoHttpd();
661 ULXR_COUT << ULXR_PCHAR("Started ") << started << ULXR_PCHAR(" threads for dispatching http and rpc requests\n");
662
663 if (shutme)
664 {
665 ULXR_COUT << ULXR_CHAR("sleep before shutting down\n");
666 #ifdef __unix__
667 usleep(5 * 1000 * 1000);
668 #elif defined(__WIN32__)
669 Sleep(5 * 1000);
670 #else
671 #error platform not supported
672 #endif
673 ULXR_COUT << ULXR_CHAR("shutdownAllThreads\n");
674 #ifdef ULXR_MULTITHREADED
675 http_server.shutdownAllThreads();
676 #endif
677 }
678
679 #ifdef ULXR_MULTITHREADED
680
681 if (started >= 1)
682 http_server.waitAsync(false, true);
683
684 #endif
685
686 ULXR_COUT << ULXR_PCHAR("Done.\n");
687 }
688
689 catch(ulxr::Exception &ex)
690 {
691 ULXR_COUT << ULXR_CHAR("Error occured: ") << ex.why() << std::endl;
692 ret = 1;
693 }
694
695 catch(...)
696 {
697 ULXR_COUT << ULXR_CHAR("unknown Error occured.\n");
698 ret = 1;
699 }
700
701 if (!ret)
702 ULXR_COUT << ULXR_CHAR("Ready and ok.\n");
703 else
704 ULXR_COUT << ULXR_CHAR("Ready but not ok.\n");
705
706 return ret;
707 }
708
709