switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / Utils / Console / UDPServer.cc
1 // $Id$
2 //
3 // Copyright (C) 2009
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief UDPServer non-inline non-template implementation */
30
31 #include "UDPServer.hh"
32 //#include "UDPServer.ih"
33
34 // Custom includes
35 #include <boost/algorithm/string/trim.hpp>
36 #include <senf/Utils/membind.hh>
37
38 //#include "UDPServer.mpp"
39 #define prefix_
40 //-/////////////////////////////////////////////////////////////////////////////////////////////////
41
42 prefix_ senf::console::UDPServer::UDPServer(senf::INet4SocketAddress const & address)
43     : replies_ (true), emptyReplies_ (true), target_ (),
44       handle_ (senf::UDPv4ClientSocketHandle(address)),
45       readevent_ ("senf::console::UDPServer::readevent",
46                   senf::membind(&UDPServer::handleInput, this),
47                   handle_,
48                   senf::scheduler::FdEvent::EV_READ),
49       parser_ (), executor_ ()
50 {
51     if (address.address().multicast())
52         handle_.facet<senf::INet4MulticastSocketProtocol>().mcAddMembership(address.address());
53     SENF_LOG(("UDP Console server started at " << address ));
54 }
55
56 prefix_ senf::console::UDPServer::UDPServer(senf::INet6SocketAddress const & address)
57     : replies_ (true), target_ (), handle_ (senf::UDPv6ClientSocketHandle(address)),
58       readevent_ ("senf::console::UDPServer::readevent",
59                   senf::membind(&UDPServer::handleInput, this),
60                   handle_,
61                   senf::scheduler::FdEvent::EV_READ),
62       parser_ (), executor_ ()
63 {
64     if (address.address().multicast())
65         handle_.facet<senf::INet6MulticastSocketProtocol>().mcAddMembership(address.address());
66     SENF_LOG(("UDP Console server started at " << address ));
67 }
68
69 prefix_ senf::console::UDPServer & senf::console::UDPServer::replies(bool enable)
70 {
71     replies_ = enable;
72     return *this;
73 }
74
75 prefix_ senf::console::UDPServer &
76 senf::console::UDPServer::replies(senf::INet4SocketAddress const & address)
77 {
78     SENF_ASSERT( handle_.local().family() == senf::INet4SocketAddress::addressFamily,
79                  "Internal failure: INet6 address on INet4 socket ??" );
80     target_ = address;
81     return *this;
82 }
83
84 prefix_ senf::console::UDPServer &
85 senf::console::UDPServer::replies(senf::INet6SocketAddress const & address)
86 {
87     SENF_ASSERT( handle_.local().family() == senf::INet6SocketAddress::addressFamily,
88                  "Internal failure: INet4 address on INet6 socket ??" );
89     target_ = address;
90     return *this;
91 }
92
93 prefix_ senf::console::UDPServer & senf::console::UDPServer::emptyReplies(bool enable)
94 {
95     emptyReplies_ = enable;
96     return *this;
97 }
98
99 prefix_ senf::console::DirectoryNode & senf::console::UDPServer::root()
100     const
101 {
102     return executor_.chroot();
103 }
104
105 prefix_ senf::console::UDPServer & senf::console::UDPServer::root(DirectoryNode & root)
106 {
107     executor_.chroot(root);
108     return *this;
109 }
110
111 prefix_ void senf::console::UDPServer::handleInput(int events)
112 {
113     if (events != senf::scheduler::FdEvent::EV_READ) {
114         SENF_LOG((senf::log::IMPORTANT)("Input handle read error. Closing socket."));
115         readevent_.disable();
116         handle_.close();
117         return;
118     }
119
120     std::string data;
121     senf::GenericBSDSocketAddress address;
122     handle_.readfrom(data, address, 0u);
123     boost::trim(data);
124
125     executor_.cwd(executor_.chroot());
126     std::stringstream stream;
127     try {
128         parser_.parse(data, boost::bind<void>( boost::ref(executor_), boost::ref(stream), _1));
129     }
130     catch (Executor::ExitException &) {
131         // Ignored
132     }
133     catch (ExceptionMixin & ex) {
134         stream << ex.message() << '\n';
135         SENF_LOG((senf::log::IMPORTANT)("Error: " << ex.message()));
136         SENF_LOG((senf::log::NOTICE)(ex.backtrace()));
137     }
138     catch (std::exception & ex) {
139         stream << ex.what() << '\n';
140         SENF_LOG((senf::log::IMPORTANT)("Error: " << ex.what()));
141     }
142     if (replies_ && (emptyReplies_ || ! stream.str().empty())) {
143         if (target_)
144             address = target_;
145         if (stream.str().empty())
146             stream << '\0';
147         handle_.writeto(address, stream.str());
148     }
149
150 }
151
152 //-/////////////////////////////////////////////////////////////////////////////////////////////////
153 #undef prefix_
154 //#include "UDPServer.mpp"
155
156 \f
157 // Local Variables:
158 // mode: c++
159 // fill-column: 100
160 // comment-column: 40
161 // c-file-style: "senf"
162 // indent-tabs-mode: nil
163 // ispell-local-dictionary: "american"
164 // compile-command: "scons -u test"
165 // End: