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