f059c56680449368e9eb6c31822ca058421eec11
[senf.git] / 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 "../Utils/senfassert.hh"
31 #include <typeinfo>
32 #include <boost/lexical_cast.hpp>
33 #include "../Utils/TypeInfo.hh"
34
35 #define prefix_ inline
36 ///////////////////////////////cti.p///////////////////////////////////////
37
38 ///////////////////////////////////////////////////////////////////////////
39 // senf::SocketHandle<SPolicy>
40
41 template <class SPolicy>
42 prefix_ senf::SocketHandle<SPolicy>::SocketHandle()
43 {}
44
45 template <class SPolicy>
46 template <class OtherPolicy>
47 prefix_ senf::SocketHandle<SPolicy>::SocketHandle(SocketHandle<OtherPolicy> other,
48                                                               typename IsCompatible<OtherPolicy>::type *)
49     : FileHandle(other)
50 {}
51
52 template <class SPolicy>
53 template <class OtherPolicy>
54 prefix_ typename senf::SocketHandle<SPolicy>::template IsCompatible<OtherPolicy>::type const &
55 senf::SocketHandle<SPolicy>::operator=(SocketHandle<OtherPolicy> other)
56 {
57     assign(other);
58     return *this;
59 }
60
61 template <class SPolicy>
62 prefix_
63 senf::SocketHandle<SPolicy>::SocketHandle(std::auto_ptr<SocketBody> body)
64     : FileHandle(std::auto_ptr<FileBody>(body.release()))
65 {}
66
67 template <class SPolicy>
68 prefix_ senf::SocketHandle<SPolicy>::SocketHandle(FileHandle other, bool isChecked)
69     : FileHandle(other)
70 {
71     SENF_ASSERT( isChecked );
72     SENF_ASSERT( dynamic_cast<SocketBody *>(&FileHandle::body()) );
73 }
74
75 template <class SPolicy>
76 prefix_ senf::SocketBody & senf::SocketHandle<SPolicy>::body()
77 {
78     SENF_ASSERT( dynamic_cast<SocketBody *>(&FileHandle::body()) );
79     return static_cast<SocketBody &>(FileHandle::body());
80 }
81
82 template <class SPolicy>
83 prefix_ senf::SocketBody const & senf::SocketHandle<SPolicy>::body()
84     const
85 {
86     SENF_ASSERT( dynamic_cast<SocketBody const *>(&FileHandle::body()) );
87     return static_cast<SocketBody const &>(FileHandle::body());
88 }
89
90 template <class SPolicy>
91 prefix_ senf::SocketProtocol const & senf::SocketHandle<SPolicy>::protocol()
92     const
93 {
94     return body().protocol();
95 }
96
97 template <class SPolicy>
98 prefix_ void senf::SocketHandle<SPolicy>::assign(FileHandle other)
99 {
100     FileHandle::operator=(other);
101 }
102
103 template <class SPolicy>
104 prefix_ senf::SocketHandle<SPolicy>
105 senf::SocketHandle<SPolicy>::cast_static(FileHandle handle)
106 {
107     return SocketHandle(handle,true);
108 }
109
110 template <class SPolicy>
111 prefix_ senf::SocketHandle<SPolicy>
112 senf::SocketHandle<SPolicy>::cast_dynamic(FileHandle handle)
113 {
114     // throws bad_cast if the body is not a SocketBody
115     SocketBody & body (dynamic_cast<SocketBody&>(FileHandle::body(handle)));
116     // throws bad_cast if the policy is not compatible
117     SPolicy::checkBaseOf(body.protocol().policy());
118     return cast_static(handle);
119 }
120
121 template <class Target, class Source>
122 prefix_ Target senf::static_socket_cast(Source handle)
123 {
124     BOOST_STATIC_ASSERT((
125         boost::is_convertible<Source*,FileHandle*>::value &&
126         boost::is_convertible<Target*,FileHandle*>::value &&
127         ( boost::is_convertible<Source,Target>::value ||
128           boost::is_convertible<Target,Source>::value ) ));
129     SENF_ASSERT( check_socket_cast<Target>(handle) );
130     return Target::cast_static(handle);
131 }
132
133 template <class Target, class Source>
134 prefix_ Target senf::dynamic_socket_cast(Source handle)
135 {
136     BOOST_STATIC_ASSERT((
137         boost::is_convertible<Source*,FileHandle*>::value &&
138         boost::is_convertible<Target*,FileHandle*>::value &&
139         ( boost::is_convertible<Source,Target>::value ||
140           boost::is_convertible<Target,Source>::value ) ));
141     return Target::cast_dynamic(handle);
142 }
143
144 template <class Target, class Source>
145 prefix_ bool senf::check_socket_cast(Source handle)
146 {
147     BOOST_STATIC_ASSERT((
148         boost::is_convertible<Source*,FileHandle*>::value &&
149         boost::is_convertible<Target*,FileHandle*>::value &&
150         ( boost::is_convertible<Source,Target>::value ||
151           boost::is_convertible<Target,Source>::value ) ));
152     // we don't have a non-throwing variant of cast_dynamic
153     // for two reasons:
154     // a) since the handle is passed back by value, we cannot return
155     //    something like a null handle
156     // b) it is simpler to implement cast_dynamic throwig bad_cast on
157     //    failure than implementing cast_check
158     try {
159         Target::cast_dynamic(handle);
160     }
161     catch (std::bad_cast const &) {
162         return false;
163     }
164     return true;
165 }
166
167 template <class SPolicy>
168 prefix_ void senf::SocketHandle<SPolicy>::state(SocketStateMap & map, unsigned lod)
169 {
170     // We use typeid here even though the type of *this is static
171     // (SocketHandle is not polymorphic and has no vtable). This will
172     // automatically include the SocketPolicy template parameter in
173     // the type name and therefore show the \e static policy of the
174     // socket handle.
175     map["handle"] << prettyName(typeid(*this));
176     body().state(map,lod);
177 }
178
179 template <class SPolicy>
180 prefix_ std::string senf::SocketHandle<SPolicy>::dumpState(unsigned lod)
181 {
182     SocketStateMap map;
183     state(map,lod);
184     return detail::dumpState(map);
185 }
186
187 ///////////////////////////////////////////////////////////////////////////
188 // senf::ProtocolSocketBody<SProtocol>
189
190 template <class SProtocol>
191 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer)
192     : SocketBody(isServer)
193 {}
194
195 template <class SProtocol>
196 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer, int fd)
197     : SocketBody(isServer, fd)
198 {}
199
200 ///////////////////////////////////////////////////////////////////////////
201
202 template <class SPolicy>
203 prefix_ std::ostream & senf::operator<<(std::ostream & os, SocketHandle<SPolicy> handle)
204 {
205     os << handle.dumpState();
206     return os;
207 }
208
209 ///////////////////////////////cti.e///////////////////////////////////////
210 #undef prefix_
211
212 \f
213 // Local Variables:
214 // mode: c++
215 // fill-column: 100
216 // c-file-style: "senf"
217 // indent-tabs-mode: nil
218 // ispell-local-dictionary: "american"
219 // compile-command: "scons -u test"
220 // comment-column: 40
221 // End: