SocketHandle.cti
Go to the documentation of this file.
1 //
2 // Copyright (c) 2020 Fraunhofer Institute for Applied Information Technology (FIT)
3 // Network Research Group (NET)
4 // Schloss Birlinghoven, 53754 Sankt Augustin, GERMANY
5 // Contact: support@wiback.org
6 //
7 // This file is part of the SENF code tree.
8 // It is licensed under the 3-clause BSD License (aka New BSD License).
9 // See LICENSE.txt in the top level directory for details or visit
10 // https://opensource.org/licenses/BSD-3-Clause
11 //
12 
13 
14 /** \file
15  \brief SocketHandle inline template implementation
16  */
17 
18 #include "SocketHandle.ih"
19 
20 // Custom includes
21 #include <typeinfo>
22 #include <senf/Utils/senfassert.hh>
23 #include <senf/Utils/TypeInfo.hh>
24 
25 #define prefix_ inline
26 //-/////////////////////////////////////////////////////////////////////////////////////////////////
27 
28 //-/////////////////////////////////////////////////////////////////////////////////////////////////
29 // senf::SocketHandle<SPolicy>
30 
31 template <class SPolicy>
32 prefix_ senf::SocketHandle<SPolicy>::SocketHandle()
33 {}
34 
35 template <class SPolicy>
36 template <class OtherPolicy>
37 prefix_ senf::SocketHandle<SPolicy>::SocketHandle(SocketHandle<OtherPolicy> other,
38  typename IsCompatible<OtherPolicy>::type *)
39  : FileHandle(other)
40 {}
41 
42 template <class SPolicy>
43 template <class OtherPolicy>
44 prefix_ typename senf::SocketHandle<SPolicy>::template IsCompatible<OtherPolicy>::type const &
45 senf::SocketHandle<SPolicy>::operator=(SocketHandle<OtherPolicy> other)
46 {
47  assign(other);
48  return *this;
49 }
50 
51 template <class SPolicy>
52 prefix_
53 senf::SocketHandle<SPolicy>::SocketHandle(std::unique_ptr<SocketBody> body)
54  : FileHandle(std::unique_ptr<FileBody>(body.release()))
55 {}
56 
57 template <class SPolicy>
58 prefix_ senf::SocketHandle<SPolicy>::SocketHandle(FileHandle other, bool isChecked)
59  : FileHandle(other)
60 {
61  SENF_ASSERT( isChecked, "Internal failure: Wrong overload called !!" );
62  SENF_ASSERT( ! valid() || dynamic_cast<SocketBody *>(&FileHandle::body()),
63  "Internal failure: Replacing or re-assigning non-empty incompatible handle");
64 }
65 
66 template <class SPolicy>
67 prefix_ senf::SocketBody & senf::SocketHandle<SPolicy>::body()
68 {
69  SENF_ASSERT( dynamic_cast<SocketBody *>(&FileHandle::body()),
70  "Internal failure: Invalid body found it's way into SocketHandle");
71  return static_cast<SocketBody &>(FileHandle::body());
72 }
73 
74 template <class SPolicy>
75 prefix_ senf::SocketBody const & senf::SocketHandle<SPolicy>::body()
76  const
77 {
78  SENF_ASSERT( dynamic_cast<SocketBody const *>(&FileHandle::body()),
79  "Internal failure: Invalid body found it's way into SocketHandle");
80  return static_cast<SocketBody const &>(FileHandle::body());
81 }
82 
83 template <class SPolicy>
84 prefix_ senf::SocketProtocol & senf::SocketHandle<SPolicy>::protocol()
85  const
86 {
87  return body().protocol();
88 }
89 
90 template <class SPolicy>
91 prefix_ void senf::SocketHandle<SPolicy>::assign(FileHandle other)
92 {
93  FileHandle::operator=(other);
94 }
95 
96 template <class SPolicy>
97 prefix_ senf::SocketHandle<SPolicy>
98 senf::SocketHandle<SPolicy>::cast_static(FileHandle handle)
99 {
100  return SocketHandle(handle,true);
101 }
102 
103 template <class SPolicy>
104 prefix_ senf::SocketHandle<SPolicy>
105 senf::SocketHandle<SPolicy>::cast_dynamic(FileHandle handle)
106 {
107  // throws bad_cast if the body is not a SocketBody
108  SocketBody & body (dynamic_cast<SocketBody&>(FileHandle::body(handle)));
109  // throws bad_cast if the policy is not compatible (already wrapped ...)
110  SPolicy::checkBaseOf(body.protocol().policy());
111  return cast_static(handle);
112 }
113 
114 template <class Target, class Source>
115 prefix_ Target senf::static_socket_cast(Source handle)
116 {
117  BOOST_STATIC_ASSERT((
118  boost::is_convertible<Source*,FileHandle*>::value &&
119  boost::is_convertible<Target*,FileHandle*>::value &&
120  ( boost::is_convertible<Source,Target>::value ||
121  boost::is_convertible<Target,Source>::value ) ));
122  SENF_ASSERT( check_socket_cast<Target>(handle),
123  "Invalid static_socket_cast" );
124  return Target::cast_static(handle);
125 }
126 
127 template <class Target, class Source>
128 prefix_ Target senf::dynamic_socket_cast(Source handle)
129 {
130 // BOOST_STATIC_ASSERT((
131 // boost::is_convertible<Source*,FileHandle*>::value &&
132 // boost::is_convertible<Target*,FileHandle*>::value &&
133 // ( boost::is_convertible<Source,Target>::value ||
134 // boost::is_convertible<Target,Source>::value ) ));
135  try {
136  return Target::cast_dynamic(handle);
137  }
138  SENF_WRAP_EXC_MSG(std::bad_cast, "in dynamic_socket_cast()")
139 }
140 
141 template <class Target, class Source>
142 prefix_ bool senf::check_socket_cast(Source handle)
143 {
144 // BOOST_STATIC_ASSERT((
145 // boost::is_convertible<Source*,FileHandle*>::value &&
146 // boost::is_convertible<Target*,FileHandle*>::value &&
147 // ( boost::is_convertible<Source,Target>::value ||
148 // boost::is_convertible<Target,Source>::value ) ));
149  // we don't have a non-throwing variant of cast_dynamic
150  // for two reasons:
151  // a) since the handle is passed back by value, we cannot return
152  // something like a null handle
153  // b) it is simpler to implement cast_dynamic throwing bad_cast on
154  // failure than implementing cast_check
155  try {
156  Target::cast_dynamic(handle);
157  }
158  catch (std::bad_cast const &) {
159  return false;
160  }
161  return true;
162 }
163 
164 template <class SPolicy>
165 prefix_ void senf::SocketHandle<SPolicy>::state(SocketStateMap & map, unsigned lod)
166 {
167  // We use typeid here even though the type of *this is static
168  // (SocketHandle is not polymorphic and has no vtable). This will
169  // automatically include the SocketPolicy template parameter in
170  // the type name and therefore show the \e static policy of the
171  // socket handle.
172  map["handle"] << prettyName(typeid(*this));
173  if (valid()) {
174  map["valid"] << "true";
175  body().state(map,lod);
176  } else
177  map["valid"] << "false";
178 }
179 
180 template <class SPolicy>
181 prefix_ std::string senf::SocketHandle<SPolicy>::dumpState(unsigned lod)
182 {
183  SocketStateMap map;
184  state(map,lod);
185  return detail::dumpState(map);
186 }
187 
188 template <class SPolicy>
189 template <class Facet>
190 prefix_ Facet & senf::SocketHandle<SPolicy>::facet()
191 
192 {
193  try {
194  return dynamic_cast<Facet &>(protocol());
195  }
196  SENF_WRAP_EXC_MSG(std::bad_cast, "in SocketHandle::facet()")
197 }
198 
199 //-/////////////////////////////////////////////////////////////////////////////////////////////////
200 // senf::ProtocolSocketBody<SProtocol>
201 
202 template <class SProtocol>
203 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer)
204  : SocketBody(isServer)
205 {}
206 
207 template <class SProtocol>
208 prefix_ senf::ProtocolSocketBody<SProtocol>::ProtocolSocketBody(bool isServer, int fd)
209  : SocketBody(isServer, fd)
210 {}
211 
212 //-/////////////////////////////////////////////////////////////////////////////////////////////////
213 
214 template <class SPolicy>
215 prefix_ std::ostream & senf::operator<<(std::ostream & os, SocketHandle<SPolicy> handle)
216 {
217  os << handle.dumpState();
218  return os;
219 }
220 
221 //-/////////////////////////////////////////////////////////////////////////////////////////////////
222 #undef prefix_
223 
224 
225 // Local Variables:
226 // mode: c++
227 // fill-column: 100
228 // c-file-style: "senf"
229 // indent-tabs-mode: nil
230 // ispell-local-dictionary: "american"
231 // compile-command: "scons -u test"
232 // comment-column: 40
233 // End: