63db515dbbbf6c621ade12c60c24a7f5e20a4915
[senf.git] / senf / Socket / SocketHandle.cti
1 // $Id$
2 //
3 // Copyright (C) 2006
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief SocketHandle inline template implementation
25  */
26
27 #include "SocketHandle.ih"
28
29 // Custom includes
30 #include <typeinfo>
31 #include <senf/Utils/senfassert.hh>
32 #include <senf/Utils/TypeInfo.hh>
33
34 #define prefix_ inline
35 ///////////////////////////////cti.p///////////////////////////////////////
36
37 ///////////////////////////////////////////////////////////////////////////
38 // senf::SocketHandle<SPolicy>
39
40 template <class SPolicy>
41 prefix_ senf::SocketHandle<SPolicy>::SocketHandle()
42 {}
43
44 template <class SPolicy>
45 template <class OtherPolicy>
46 prefix_ senf::SocketHandle<SPolicy>::SocketHandle(SocketHandle<OtherPolicy> other,
47                                                   typename IsCompatible<OtherPolicy>::type *)
48     : FileHandle(other)
49 {}
50
51 template <class SPolicy>
52 template <class OtherPolicy>
53 prefix_ typename senf::SocketHandle<SPolicy>::template IsCompatible<OtherPolicy>::type const &
54 senf::SocketHandle<SPolicy>::operator=(SocketHandle<OtherPolicy> other)
55 {
56     assign(other);
57     return *this;
58 }
59
60 template <class SPolicy>
61 prefix_
62 senf::SocketHandle<SPolicy>::SocketHandle(std::auto_ptr<SocketBody> body)
63     : FileHandle(std::auto_ptr<FileBody>(body.release()))
64 {}
65
66 template <class SPolicy>
67 prefix_ senf::SocketHandle<SPolicy>::SocketHandle(FileHandle other, bool isChecked)
68     : FileHandle(other)
69 {
70     SENF_ASSERT( isChecked, "Inrernal failure: Wrong overload called !!" );
71     SENF_ASSERT( ! valid() || dynamic_cast<SocketBody *>(&FileHandle::body()),
72                  "Internal failure: Replacing or re-assigning non-empty incompatible handle");
73 }
74
75 template <class SPolicy>
76 prefix_ senf::SocketBody & senf::SocketHandle<SPolicy>::body()
77 {
78     SENF_ASSERT( dynamic_cast<SocketBody *>(&FileHandle::body()),
79                  "Internal failure: Invalid body found it's way into SocketHandle");
80     return static_cast<SocketBody &>(FileHandle::body());
81 }
82
83 template <class SPolicy>
84 prefix_ senf::SocketBody const & senf::SocketHandle<SPolicy>::body()
85     const
86 {
87     SENF_ASSERT( dynamic_cast<SocketBody const *>(&FileHandle::body()),
88                  "Internal failure: Invalid body found it's way into SocketHandle");
89     return static_cast<SocketBody const &>(FileHandle::body());
90 }
91
92 template <class SPolicy>
93 prefix_ senf::SocketProtocol & senf::SocketHandle<SPolicy>::protocol()
94     const
95 {
96     return body().protocol();
97 }
98
99 template <class SPolicy>
100 prefix_ void senf::SocketHandle<SPolicy>::assign(FileHandle other)
101 {
102     FileHandle::operator=(other);
103 }
104
105 template <class SPolicy>
106 prefix_ senf::SocketHandle<SPolicy>
107 senf::SocketHandle<SPolicy>::cast_static(FileHandle handle)
108 {
109     return SocketHandle(handle,true);
110 }
111
112 template <class SPolicy>
113 prefix_ senf::SocketHandle<SPolicy>
114 senf::SocketHandle<SPolicy>::cast_dynamic(FileHandle handle)
115 {
116     // throws bad_cast if the body is not a SocketBody
117     SocketBody & body (dynamic_cast<SocketBody&>(FileHandle::body(handle)));
118     // throws bad_cast if the policy is not compatible (already wrapped ...)
119     SPolicy::checkBaseOf(body.protocol().policy());
120     return cast_static(handle);
121 }
122
123 template <class Target, class Source>
124 prefix_ Target senf::static_socket_cast(Source handle)
125 {
126     BOOST_STATIC_ASSERT((
127         boost::is_convertible<Source*,FileHandle*>::value &&
128         boost::is_convertible<Target*,FileHandle*>::value &&
129         ( boost::is_convertible<Source,Target>::value ||
130           boost::is_convertible<Target,Source>::value ) ));
131     SENF_ASSERT( check_socket_cast<Target>(handle),
132                  "Invalid static_socket_cast" );
133     return Target::cast_static(handle);
134 }
135
136 template <class Target, class Source>
137 prefix_ Target senf::dynamic_socket_cast(Source handle)
138 {
139 //     BOOST_STATIC_ASSERT((
140 //         boost::is_convertible<Source*,FileHandle*>::value &&
141 //         boost::is_convertible<Target*,FileHandle*>::value &&
142 //         ( boost::is_convertible<Source,Target>::value ||
143 //           boost::is_convertible<Target,Source>::value ) ));
144     try {
145         return Target::cast_dynamic(handle);
146     }
147     SENF_WRAP_EXC(std::bad_cast)
148 }
149
150 template <class Target, class Source>
151 prefix_ bool senf::check_socket_cast(Source handle)
152 {
153 //     BOOST_STATIC_ASSERT((
154 //         boost::is_convertible<Source*,FileHandle*>::value &&
155 //         boost::is_convertible<Target*,FileHandle*>::value &&
156 //         ( boost::is_convertible<Source,Target>::value ||
157 //           boost::is_convertible<Target,Source>::value ) ));
158     // we don't have a non-throwing variant of cast_dynamic
159     // for two reasons:
160     // a) since the handle is passed back by value, we cannot return
161     //    something like a null handle
162     // b) it is simpler to implement cast_dynamic throwig bad_cast on
163     //    failure than implementing cast_check
164     try {
165         Target::cast_dynamic(handle);
166     }
167     catch (std::bad_cast const &) {
168         return false;
169     }
170     return true;
171 }
172
173 template <class SPolicy>
174 prefix_ void senf::SocketHandle<SPolicy>::state(SocketStateMap & map, unsigned lod)
175 {
176     // We use typeid here even though the type of *this is static
177     // (SocketHandle is not polymorphic and has no vtable). This will
178     // automatically include the SocketPolicy template parameter in
179     // the type name and therefore show the \e static policy of the
180     // socket handle.
181     map["handle"] << prettyName(typeid(*this));
182     if (valid()) {
183         map["valid"] << "true";
184         body().state(map,lod);
185     } else
186         map["valid"] << "false";
187 }
188
189 template <class SPolicy>
190 prefix_ std::string senf::SocketHandle<SPolicy>::dumpState(unsigned lod)
191 {
192     SocketStateMap map;
193     state(map,lod);
194     return detail::dumpState(map);
195 }
196
197 template <class SPolicy>
198 template <class Facet>
199 prefix_ Facet & senf::SocketHandle<SPolicy>::facet()
200
201 {
202     try {
203         return dynamic_cast<Facet &>(protocol());
204     }
205     SENF_WRAP_EXC(std::bad_cast)
206 }
207
208 ///////////////////////////////////////////////////////////////////////////
209 // senf::ProtocolSocketBody<SProtocol>
210
211 template <class SProtocol>
212 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer)
213     : SocketBody(isServer)
214 {}
215
216 template <class SProtocol>
217 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer, int fd)
218     : SocketBody(isServer, fd)
219 {}
220
221 ///////////////////////////////////////////////////////////////////////////
222
223 template <class SPolicy>
224 prefix_ std::ostream & senf::operator<<(std::ostream & os, SocketHandle<SPolicy> handle)
225 {
226     os << handle.dumpState();
227     return os;
228 }
229
230 ///////////////////////////////cti.e///////////////////////////////////////
231 #undef prefix_
232
233 \f
234 // Local Variables:
235 // mode: c++
236 // fill-column: 100
237 // c-file-style: "senf"
238 // indent-tabs-mode: nil
239 // ispell-local-dictionary: "american"
240 // compile-command: "scons -u test"
241 // comment-column: 40
242 // End: