Move sourcecode into 'senf/' directory
[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 "../Utils/senfassert.hh"
32 #include "../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 );
71     SENF_ASSERT( ! valid() || dynamic_cast<SocketBody *>(&FileHandle::body()) );
72 }
73
74 template <class SPolicy>
75 prefix_ senf::SocketBody & senf::SocketHandle<SPolicy>::body()
76 {
77     SENF_ASSERT( dynamic_cast<SocketBody *>(&FileHandle::body()) );
78     return static_cast<SocketBody &>(FileHandle::body());
79 }
80
81 template <class SPolicy>
82 prefix_ senf::SocketBody const & senf::SocketHandle<SPolicy>::body()
83     const
84 {
85     SENF_ASSERT( dynamic_cast<SocketBody const *>(&FileHandle::body()) );
86     return static_cast<SocketBody const &>(FileHandle::body());
87 }
88
89 template <class SPolicy>
90 prefix_ senf::SocketProtocol & senf::SocketHandle<SPolicy>::protocol()
91     const
92 {
93     return body().protocol();
94 }
95
96 template <class SPolicy>
97 prefix_ void senf::SocketHandle<SPolicy>::assign(FileHandle other)
98 {
99     FileHandle::operator=(other);
100 }
101
102 template <class SPolicy>
103 prefix_ senf::SocketHandle<SPolicy>
104 senf::SocketHandle<SPolicy>::cast_static(FileHandle handle)
105 {
106     return SocketHandle(handle,true);
107 }
108
109 template <class SPolicy>
110 prefix_ senf::SocketHandle<SPolicy>
111 senf::SocketHandle<SPolicy>::cast_dynamic(FileHandle handle)
112 {
113     // throws bad_cast if the body is not a SocketBody
114     SocketBody & body (dynamic_cast<SocketBody&>(FileHandle::body(handle)));
115     // throws bad_cast if the policy is not compatible (already wrapped ...)
116     SPolicy::checkBaseOf(body.protocol().policy());
117     return cast_static(handle);
118 }
119
120 template <class Target, class Source>
121 prefix_ Target senf::static_socket_cast(Source handle)
122 {
123     BOOST_STATIC_ASSERT((
124         boost::is_convertible<Source*,FileHandle*>::value &&
125         boost::is_convertible<Target*,FileHandle*>::value &&
126         ( boost::is_convertible<Source,Target>::value ||
127           boost::is_convertible<Target,Source>::value ) ));
128     SENF_ASSERT( check_socket_cast<Target>(handle) );
129     return Target::cast_static(handle);
130 }
131
132 template <class Target, class Source>
133 prefix_ Target senf::dynamic_socket_cast(Source handle)
134 {
135 //     BOOST_STATIC_ASSERT((
136 //         boost::is_convertible<Source*,FileHandle*>::value &&
137 //         boost::is_convertible<Target*,FileHandle*>::value &&
138 //         ( boost::is_convertible<Source,Target>::value ||
139 //           boost::is_convertible<Target,Source>::value ) ));
140     try {
141         return Target::cast_dynamic(handle);
142     }
143     SENF_WRAP_EXC(std::bad_cast)
144 }
145
146 template <class Target, class Source>
147 prefix_ bool senf::check_socket_cast(Source handle)
148 {
149 //     BOOST_STATIC_ASSERT((
150 //         boost::is_convertible<Source*,FileHandle*>::value &&
151 //         boost::is_convertible<Target*,FileHandle*>::value &&
152 //         ( boost::is_convertible<Source,Target>::value ||
153 //           boost::is_convertible<Target,Source>::value ) ));
154     // we don't have a non-throwing variant of cast_dynamic
155     // for two reasons:
156     // a) since the handle is passed back by value, we cannot return
157     //    something like a null handle
158     // b) it is simpler to implement cast_dynamic throwig bad_cast on
159     //    failure than implementing cast_check
160     try {
161         Target::cast_dynamic(handle);
162     }
163     catch (std::bad_cast const &) {
164         return false;
165     }
166     return true;
167 }
168
169 template <class SPolicy>
170 prefix_ void senf::SocketHandle<SPolicy>::state(SocketStateMap & map, unsigned lod)
171 {
172     // We use typeid here even though the type of *this is static
173     // (SocketHandle is not polymorphic and has no vtable). This will
174     // automatically include the SocketPolicy template parameter in
175     // the type name and therefore show the \e static policy of the
176     // socket handle.
177     map["handle"] << prettyName(typeid(*this));
178     if (valid()) {
179         map["valid"] << "true";
180         body().state(map,lod);
181     } else
182         map["valid"] << "false";
183 }
184
185 template <class SPolicy>
186 prefix_ std::string senf::SocketHandle<SPolicy>::dumpState(unsigned lod)
187 {
188     SocketStateMap map;
189     state(map,lod);
190     return detail::dumpState(map);
191 }
192
193 template <class SPolicy>
194 template <class Facet>
195 prefix_ Facet & senf::SocketHandle<SPolicy>::facet()
196
197 {
198     try {
199         return dynamic_cast<Facet &>(protocol());
200     }
201     SENF_WRAP_EXC(std::bad_cast)
202 }
203
204 ///////////////////////////////////////////////////////////////////////////
205 // senf::ProtocolSocketBody<SProtocol>
206
207 template <class SProtocol>
208 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer)
209     : SocketBody(isServer)
210 {}
211
212 template <class SProtocol>
213 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer, int fd)
214     : SocketBody(isServer, fd)
215 {}
216
217 ///////////////////////////////////////////////////////////////////////////
218
219 template <class SPolicy>
220 prefix_ std::ostream & senf::operator<<(std::ostream & os, SocketHandle<SPolicy> handle)
221 {
222     os << handle.dumpState();
223     return os;
224 }
225
226 ///////////////////////////////cti.e///////////////////////////////////////
227 #undef prefix_
228
229 \f
230 // Local Variables:
231 // mode: c++
232 // fill-column: 100
233 // c-file-style: "senf"
234 // indent-tabs-mode: nil
235 // ispell-local-dictionary: "american"
236 // compile-command: "scons -u test"
237 // comment-column: 40
238 // End: