2a4a7b47fe2b8b877c5b87a29fd6f4c916e1ae15
[libt2n] / src / command_server.cpp
1 /***************************************************************************
2  *   Copyright (C) 2006 by Gerd v. Egidy                                   *
3  *   gve@intra2net.com                                                     *
4  *                                                                         *
5  *   This library is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU Lesser General Public License version   *
7  *   2.1 as published by the Free Software Foundation.                     *
8  *                                                                         *
9  *   This library is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU Lesser General Public License for more details.                   *
13  *                                                                         *
14  *   You should have received a copy of the GNU Lesser General Public      *
15  *   License along with this program; if not, write to the                 *
16  *   Free Software Foundation, Inc.,                                       *
17  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18  ***************************************************************************/
19
20 #include <string>
21 #include <sstream>
22 #include <stdexcept>
23 #include <iostream>
24
25 #include <boost/archive/binary_oarchive.hpp>
26 #include <boost/archive/binary_iarchive.hpp>
27 #include <boost/archive/xml_oarchive.hpp>
28 #include <boost/archive/xml_iarchive.hpp>
29 #include <boost/serialization/serialization.hpp>
30
31 #include <boost/bind.hpp>
32
33 #include "command_server.hxx"
34 #include "container.hxx"
35 #include "log.hxx"
36
37 using namespace std;
38
39 namespace libt2n
40 {
41
42 command_server::command_server(server& _s)
43     : s(_s)
44 {
45     // register callback
46     s.add_callback(new_connection,bind(&command_server::new_connection_callback, boost::ref(*this), _1));
47 }
48
49 void command_server::new_connection_callback(unsigned int conn_id)
50 {
51     cerr << "new connection callback: " << conn_id << endl;
52 }
53
54 /// handle a command including deserialization and answering
55 void command_server::handle_packet(const std::string& packet, server_connection* conn)
56 {
57     OBJLOGSTREAM(s,debug,"handling packet from connection " << conn->get_id());
58
59     // deserialize packet
60     istringstream ifs(packet);
61     boost::archive::binary_iarchive ia(ifs);
62     command_container ccont;
63
64     // TODO: catch
65     ia >> ccont;
66
67     std::ostream* ostr;
68     if ((ostr=s.get_logstream(fulldebug))!=NULL)
69     {
70         (*ostr) << "decoded packet data: " << std::endl;
71         boost::archive::xml_oarchive xo(*ostr);
72         xo << BOOST_SERIALIZATION_NVP(ccont);
73     }
74
75     // TODO: cast to command subclass (template)
76     command *cmd=ccont.get_command();
77
78     result_container res;
79
80     if (cmd)
81     {
82         try
83         {
84             res.set_result((*cmd)());
85         }
86         catch (t2n_exception &e)
87             { res.set_exception(e.clone()); }
88         catch (...)
89             { throw; }
90     }
91     else
92         throw logic_error("uninitialized command called");
93
94     ostringstream ofs;
95     boost::archive::binary_oarchive oa(ofs);
96
97     // TODO: catch
98     oa << res;
99
100     if ((ostr=s.get_logstream(fulldebug))!=NULL)
101     {
102         (*ostr) << "returning result, decoded data: " << std::endl;
103         boost::archive::xml_oarchive xo(*ostr);
104         xo << BOOST_SERIALIZATION_NVP(res);
105     }
106
107     conn->write(ofs.str());
108 }
109
110 /** @brief handle incoming commands
111     @param usec_timeout wait until new data is found, max timeout usecs.
112             -1: wait endless, 0: no timeout
113 */
114 void command_server::handle(long long usec_timeout)
115 {
116     if (s.fill_buffer(usec_timeout))
117     {
118         string packet;
119         unsigned int conn_id;
120
121         while (s.get_packet(packet,conn_id))
122             handle_packet(packet,s.get_connection(conn_id)); 
123     }
124     s.cleanup();
125 }
126
127 }