JINMEI Tatuya committed May 27, 2010 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ``````// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") // // Permission to use, copy, modify, and/or distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR // PERFORMANCE OF THIS SOFTWARE. // \$Id\$ #ifndef __ASIO_LINK_H #define __ASIO_LINK_H 1 `````` JINMEI Tatuya committed Jun 22, 2010 20 21 ``````// IMPORTANT NOTE: only very few ASIO headers files can be included in // this file. In particular, asio.hpp should never be included here. `````` JINMEI Tatuya committed Jun 21, 2010 22 ``````// See the description of the namespace below. `````` JINMEI Tatuya committed Jul 22, 2010 23 ``````#include // for some network system calls `````` JINMEI Tatuya committed Jun 21, 2010 24 25 ``````#include `````` JINMEI Tatuya committed Jun 20, 2010 26 ``````#include `````` JINMEI Tatuya committed Jun 19, 2010 27 28 ``````#include `````` JINMEI Tatuya committed Jun 20, 2010 29 30 ``````#include `````` JINMEI Tatuya committed Jun 19, 2010 31 32 33 ``````#include namespace asio { `````` JINMEI Tatuya committed Jul 21, 2010 34 ``````// forward declaration for IOService::get_io_service() below `````` JINMEI Tatuya committed Jun 19, 2010 35 36 37 ``````class io_service; } `````` JINMEI Tatuya committed May 27, 2010 38 39 ``````class AuthSrv; `````` JINMEI Tatuya committed Jun 21, 2010 40 41 42 43 44 ``````/// \namespace asio_link /// \brief A wrapper interface for the ASIO library. /// /// The \c asio_link namespace is used to define a set of wrapper interfaces /// for the ASIO library. `````` Evan Hunt committed Jul 20, 2010 45 46 47 ``````/// /// BIND 10 uses the non-Boost version of ASIO because it's header-only, /// i.e., does not require a separate library object to be linked, and thus `````` JINMEI Tatuya committed Jun 21, 2010 48 ``````/// lowers the bar for introduction. `````` Evan Hunt committed Jul 20, 2010 49 50 ``````/// /// But the advantage comes with its own costs: since the header-only version `````` JINMEI Tatuya committed Jun 21, 2010 51 52 53 ``````/// includes more definitions in public header files, it tends to trigger /// more compiler warnings for our own sources, and, depending on the /// compiler options, may make the build fail. `````` Evan Hunt committed Jul 20, 2010 54 ``````/// `````` JINMEI Tatuya committed Jun 21, 2010 55 56 ``````/// We also found it may be tricky to use ASIO and standard C++ libraries /// in a single translation unit, i.e., a .cc file: depending on the order `````` Evan Hunt committed Jul 20, 2010 57 58 59 ``````/// of including header files, ASIO may or may not work on some platforms. /// /// This wrapper interface is intended to centralize these `````` JINMEI Tatuya committed Jun 21, 2010 60 ``````/// problematic issues in a single sub module. Other BIND 10 modules should `````` Evan Hunt committed Jul 20, 2010 61 62 ``````/// simply include \c asio_link.h and use the wrapper API instead of /// including ASIO header files and using ASIO-specific classes directly. `````` JINMEI Tatuya committed Jun 21, 2010 63 64 65 66 67 68 ``````/// /// This wrapper may be used for other IO libraries if and when we want to /// switch, but generality for that purpose is not the primary goal of /// this module. The resulting interfaces are thus straightforward mapping /// to the ASIO counterparts. /// `````` JINMEI Tatuya committed Jun 22, 2010 69 70 ``````/// Notes to developers: /// Currently the wrapper interface is specific to the authoritative `````` JINMEI Tatuya committed Jun 21, 2010 71 72 73 ``````/// server implementation. But the plan is to generalize it and have /// other modules use it. /// `````` JINMEI Tatuya committed Jun 22, 2010 74 ``````/// One obvious drawback of this approach is performance overhead `````` JINMEI Tatuya committed Jun 21, 2010 75 ``````/// due to the additional layer. We should eventually evaluate the cost `````` Evan Hunt committed Jul 20, 2010 76 77 78 ``````/// of the wrapper abstraction in benchmark tests. Another drawback is /// that the wrapper interfaces don't provide all features of ASIO /// (at least for the moment). We should also re-evaluate the `````` JINMEI Tatuya committed Jun 21, 2010 79 80 ``````/// maintenance overhead of providing necessary wrappers as we develop /// more. `````` JINMEI Tatuya committed Jun 22, 2010 81 82 83 84 ``````/// /// On the other hand, we may be able to exploit the wrapper approach to /// simplify the interfaces (by limiting the usage) and unify performance /// optimization points. `````` Evan Hunt committed Jul 20, 2010 85 ``````/// `````` JINMEI Tatuya committed Jun 22, 2010 86 87 88 ``````/// As for optimization, we may want to provide a custom allocator for /// the placeholder of callback handlers: /// http://think-async.com/Asio/asio-1.3.1/doc/asio/reference/asio_handler_allocate.html `````` JINMEI Tatuya committed Jun 21, 2010 89 `````` `````` JINMEI Tatuya committed May 27, 2010 90 ``````namespace asio_link { `````` JINMEI Tatuya committed Oct 09, 2010 91 ``````class IOServiceImpl; `````` JINMEI Tatuya committed May 27, 2010 92 `````` `````` JINMEI Tatuya committed Jun 20, 2010 93 ``````/// \brief An exception that is thrown if an error occurs within the IO `````` JINMEI Tatuya committed Jun 19, 2010 94 95 96 97 98 99 100 101 ``````/// module. This is mainly intended to be a wrapper exception class for /// ASIO specific exceptions. class IOError : public isc::Exception { public: IOError(const char* file, size_t line, const char* what) : isc::Exception(file, line, what) {} }; `````` JINMEI Tatuya committed Jun 21, 2010 102 103 104 105 ``````/// \brief The \c IOAddress class represents an IP addresses (version /// agnostic) /// /// This class is a wrapper for the ASIO \c ip::address class. `````` JINMEI Tatuya committed Jun 19, 2010 106 107 ``````class IOAddress { public: `````` JINMEI Tatuya committed Jun 21, 2010 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 `````` /// /// \name Constructors and Destructor /// /// This class is copyable. We use default versions of copy constructor /// and the assignment operator. /// We use the default destructor. //@{ /// \brief Constructor from string. /// /// This constructor converts a textual representation of IPv4 and IPv6 /// addresses into an IOAddress object. /// If \c address_str is not a valid representation of any type of /// address, an exception of class \c IOError will be thrown. /// This constructor allocates memory for the object, and if that fails /// a corresponding standard exception will be thrown. /// /// \param address_str Textual representation of address. IOAddress(const std::string& address_str); /// \brief Constructor from an ASIO \c ip::address object. /// /// This constructor is intended to be used within the wrapper /// implementation; user applications of the wrapper API won't use it. /// /// This constructor never throws an exception. /// /// \param asio_address The ASIO \c ip::address to be converted. `````` Jeremy C. Reed committed Nov 16, 2010 135 `````` IOAddress(const asio::ip::address& asio_address); `````` JINMEI Tatuya committed Jun 21, 2010 136 137 138 139 140 141 142 143 144 `````` //@} /// \brief Convert the address to a string. /// /// This method is basically expected to be exception free, but /// generating the string will involve resource allocation, /// and if it fails the corresponding standard exception will be thrown. /// /// \return A string representation of the address. `````` JINMEI Tatuya committed Jun 19, 2010 145 146 `````` std::string toText() const; private: `````` JINMEI Tatuya committed Jun 21, 2010 147 `````` asio::ip::address asio_address_; `````` JINMEI Tatuya committed Jun 19, 2010 148 149 ``````}; `````` JINMEI Tatuya committed Jun 22, 2010 150 151 152 153 154 155 156 157 158 ``````/// \brief The \c IOEndpoint class is an abstract base class to represent /// a communication endpoint. /// /// This class is a wrapper for the ASIO endpoint classes such as /// \c ip::tcp::endpoint and \c ip::udp::endpoint. /// /// Derived class implementations are completely hidden within the /// implementation. User applications only get access to concrete /// \c IOEndpoint objects via the abstract interfaces. `````` JINMEI Tatuya committed Jun 21, 2010 159 ``````class IOEndpoint { `````` JINMEI Tatuya committed Jun 22, 2010 160 161 162 163 164 165 `````` /// /// \name Constructors and Destructor /// /// Note: The copy constructor and the assignment operator are /// intentionally defined as private, making this class non-copyable. //@{ `````` JINMEI Tatuya committed Jun 21, 2010 166 167 168 169 ``````private: IOEndpoint(const IOEndpoint& source); IOEndpoint& operator=(const IOEndpoint& source); protected: `````` JINMEI Tatuya committed Jun 22, 2010 170 171 172 173 `````` /// \brief The default constructor. /// /// This is intentionally defined as \c protected as this base class /// should never be instantiated (except as part of a derived class). `````` JINMEI Tatuya committed Jun 21, 2010 174 175 `````` IOEndpoint() {} public: `````` JINMEI Tatuya committed Jun 22, 2010 176 `````` /// The destructor. `````` JINMEI Tatuya committed Jun 21, 2010 177 `````` virtual ~IOEndpoint() {} `````` JINMEI Tatuya committed Jun 22, 2010 178 179 180 181 182 183 `````` //@} /// \brief Returns the address of the endpoint. /// /// This method returns an IOAddress object corresponding to \c this /// endpoint. `````` Evan Hunt committed Jul 20, 2010 184 `````` /// Note that the return value is a real object, not a reference or `````` JINMEI Tatuya committed Jun 22, 2010 185 186 187 188 189 190 191 192 193 194 195 196 `````` /// a pointer. /// This is aligned with the interface of the ASIO counterpart: /// the \c address() method of \c ip::xxx::endpoint classes returns /// an \c ip::address object. /// This also means handling the address of an endpoint using this method /// can be expensive. If the address information is necessary in a /// performance sensitive context and there's a more efficient interface /// for that purpose, it's probably better to avoid using this method. /// /// This method never throws an exception. /// /// \return A copy of \c IOAddress object corresponding to the endpoint. `````` JINMEI Tatuya committed Jun 21, 2010 197 `````` virtual IOAddress getAddress() const = 0; `````` JINMEI Tatuya committed Jun 22, 2010 198 199 200 201 202 203 204 205 206 207 208 209 `````` /// \brief A polymorphic factory of endpoint from address and port. /// /// This method creates a new instance of (a derived class of) /// \c IOEndpoint object that identifies the pair of given address /// and port. /// The appropriate derived class is chosen based on the specified /// transport protocol. If the \c protocol doesn't specify a protocol /// supported in this implementation, an exception of class \c IOError /// will be thrown. /// /// Memory for the created object will be dynamically allocated. It's `````` Jeremy C. Reed committed Aug 23, 2010 210 `````` /// the caller's responsibility to \c delete it later. `````` JINMEI Tatuya committed Jun 22, 2010 211 212 213 214 215 216 217 218 `````` /// If resource allocation for the new object fails, a corresponding /// standard exception will be thrown. /// /// \param protocol The transport protocol used for the endpoint. /// Currently, only \c IPPROTO_UDP and \c IPPROTO_TCP can be specified. /// \param address The (IP) address of the endpoint. /// \param port The transport port number of the endpoint /// \return A pointer to a newly created \c IOEndpoint object. `````` 219 `````` static const IOEndpoint* create(const int protocol, `````` JINMEI Tatuya committed Jun 22, 2010 220 `````` const IOAddress& address, `````` 221 `````` const unsigned short port); `````` JINMEI Tatuya committed Jun 21, 2010 222 223 224 225 226 227 228 229 ``````}; /// \brief The \c IOSocket class is an abstract base class to represent /// various types of network sockets. /// /// This class is a wrapper for the ASIO socket classes such as /// \c ip::tcp::socket and \c ip::udp::socket. /// `````` JINMEI Tatuya committed Jun 22, 2010 230 ``````/// Derived class implementations are completely hidden within the `````` JINMEI Tatuya committed Jun 21, 2010 231 232 ``````/// implementation. User applications only get access to concrete /// \c IOSocket objects via the abstract interfaces. `````` JINMEI Tatuya committed Jul 21, 2010 233 234 235 236 ``````/// We may revisit this decision when we generalize the wrapper and more /// modules use it. Also, at that point we may define a separate (visible) /// derived class for testing purposes rather than providing factory methods /// (i.e., getDummy variants below). `````` JINMEI Tatuya committed Jun 20, 2010 237 ``````class IOSocket { `````` JINMEI Tatuya committed Jun 21, 2010 238 239 240 241 242 243 `````` /// /// \name Constructors and Destructor /// /// Note: The copy constructor and the assignment operator are /// intentionally defined as private, making this class non-copyable. //@{ `````` JINMEI Tatuya committed Jun 20, 2010 244 245 246 247 ``````private: IOSocket(const IOSocket& source); IOSocket& operator=(const IOSocket& source); protected: `````` JINMEI Tatuya committed Jun 21, 2010 248 249 250 251 `````` /// \brief The default constructor. /// /// This is intentionally defined as \c protected as this base class /// should never be instantiated (except as part of a derived class). `````` JINMEI Tatuya committed Jun 20, 2010 252 253 `````` IOSocket() {} public: `````` JINMEI Tatuya committed Jun 21, 2010 254 `````` /// The destructor. `````` JINMEI Tatuya committed Jun 20, 2010 255 `````` virtual ~IOSocket() {} `````` JINMEI Tatuya committed Jun 21, 2010 256 257 258 259 260 261 262 263 264 265 266 `````` //@} /// \brief Return the "native" representation of the socket. /// /// In practice, this is the file descriptor of the socket for /// UNIX-like systems so the current implementation simply uses /// \c int as the type of the return value. /// We may have to need revisit this decision later. /// /// In general, the application should avoid using this method; /// it essentially discloses an implementation specific "handle" that `````` JINMEI Tatuya committed Jul 21, 2010 267 `````` /// can change the internal state of the socket (consider the `````` JINMEI Tatuya committed Jun 21, 2010 268 269 270 271 272 273 274 275 276 277 `````` /// application closes it, for example). /// But we sometimes need to perform very low-level operations that /// requires the native representation. Passing the file descriptor /// to a different process is one example. /// This method is provided as a necessary evil for such limited purposes. /// /// This method never throws an exception. /// /// \return The native representation of the socket. This is the socket /// file descriptor for UNIX-like systems. `````` JINMEI Tatuya committed Jun 20, 2010 278 `````` virtual int getNative() const = 0; `````` JINMEI Tatuya committed Jun 21, 2010 279 280 281 282 283 284 285 286 287 288 `````` /// \brief Return the transport protocol of the socket. /// /// Currently, it returns \c IPPROTO_UDP for UDP sockets, and /// \c IPPROTO_TCP for TCP sockets. /// /// This method never throws an exception. /// /// \return IPPROTO_UDP for UDP sockets /// \return IPPROTO_TCP for TCP sockets `````` JINMEI Tatuya committed Jun 20, 2010 289 `````` virtual int getProtocol() const = 0; `````` JINMEI Tatuya committed Jun 21, 2010 290 291 292 293 294 295 296 297 298 299 300 301 302 303 `````` /// \brief Return a non-usable "dummy" UDP socket for testing. /// /// This is a class method that returns a "mock" of UDP socket. /// This is not associated with any actual socket, and its only /// responsibility is to return \c IPPROTO_UDP from \c getProtocol(). /// The only feasible usage of this socket is for testing so that /// the test code can prepare some "UDP data" even without opening any /// actual socket. /// /// This method never throws an exception. /// /// \return A reference to an \c IOSocket object whose \c getProtocol() /// returns \c IPPROTO_UDP. `````` JINMEI Tatuya committed Jun 20, 2010 304 `````` static IOSocket& getDummyUDPSocket(); `````` JINMEI Tatuya committed Jun 21, 2010 305 306 307 308 309 310 311 `````` /// \brief Return a non-usable "dummy" TCP socket for testing. /// /// See \c getDummyUDPSocket(). This method is its TCP version. /// /// \return A reference to an \c IOSocket object whose \c getProtocol() /// returns \c IPPROTO_TCP. `````` JINMEI Tatuya committed Jun 20, 2010 312 `````` static IOSocket& getDummyTCPSocket(); `````` JINMEI Tatuya committed Jun 20, 2010 313 314 ``````}; `````` JINMEI Tatuya committed Jun 22, 2010 315 316 ``````/// \brief The \c IOMessage class encapsulates an incoming message received /// on a socket. `````` JINMEI Tatuya committed Jun 21, 2010 317 318 319 320 321 322 323 324 325 ``````/// /// An \c IOMessage object represents a tuple of a chunk of data /// (a UDP packet or some segment of TCP stream), the socket over which the /// data is passed, the information about the other end point of the /// communication, and perhaps more. /// /// The current design and interfaces of this class is tentative. /// It only provides a minimal level of support that is necessary for /// the current implementation of the authoritative server. `````` JINMEI Tatuya committed Jun 22, 2010 326 ``````/// A future version of this class will definitely support more. `````` JINMEI Tatuya committed Jun 19, 2010 327 ``````class IOMessage { `````` JINMEI Tatuya committed Jun 21, 2010 328 329 330 331 332 333 `````` /// /// \name Constructors and Destructor /// /// Note: The copy constructor and the assignment operator are /// intentionally defined as private, making this class non-copyable. //@{ `````` JINMEI Tatuya committed Jun 19, 2010 334 335 336 ``````private: IOMessage(const IOMessage& source); IOMessage& operator=(const IOMessage& source); `````` JINMEI Tatuya committed Jun 19, 2010 337 ``````public: `````` JINMEI Tatuya committed Jun 21, 2010 338 339 340 341 342 343 344 345 346 347 348 349 350 `````` /// \brief Constructor from message information. /// /// This constructor needs to handle the ASIO \c ip::address class, /// and is intended to be used within this wrapper implementation. /// Once the \c IOMessage object is created, the application can /// get access to the information via the wrapper interface such as /// \c getRemoteAddress(). /// /// This constructor never throws an exception. /// /// \param data A pointer to the message data. /// \param data_size The size of the message data in bytes. /// \param io_socket The socket over which the data is given. `````` JINMEI Tatuya committed Jun 22, 2010 351 352 `````` /// \param remote_endpoint The other endpoint of the socket, that is, /// the sender of the message. `````` 353 `````` IOMessage(const void* data, const size_t data_size, IOSocket& io_socket, `````` JINMEI Tatuya committed Jun 21, 2010 354 355 `````` const IOEndpoint& remote_endpoint); //@} `````` JINMEI Tatuya committed Jun 22, 2010 356 357 `````` /// \brief Returns a pointer to the received data. `````` JINMEI Tatuya committed Jun 20, 2010 358 `````` const void* getData() const { return (data_); } `````` JINMEI Tatuya committed Jun 22, 2010 359 360 `````` /// \brief Returns the size of the received data in bytes. `````` JINMEI Tatuya committed Jun 20, 2010 361 `````` size_t getDataSize() const { return (data_size_); } `````` JINMEI Tatuya committed Jun 22, 2010 362 363 `````` /// \brief Returns the socket on which the message arrives. `````` JINMEI Tatuya committed Jun 20, 2010 364 `````` const IOSocket& getSocket() const { return (io_socket_); } `````` JINMEI Tatuya committed Jun 22, 2010 365 366 `````` /// \brief Returns the endpoint that sends the message. `````` JINMEI Tatuya committed Jun 21, 2010 367 `````` const IOEndpoint& getRemoteEndpoint() const { return (remote_endpoint_); } `````` JINMEI Tatuya committed Jun 19, 2010 368 ``````private: `````` JINMEI Tatuya committed Jun 20, 2010 369 370 371 `````` const void* data_; const size_t data_size_; IOSocket& io_socket_; `````` JINMEI Tatuya committed Jun 21, 2010 372 `````` const IOEndpoint& remote_endpoint_; `````` JINMEI Tatuya committed Jun 19, 2010 373 374 ``````}; `````` JINMEI Tatuya committed Jun 22, 2010 375 376 377 378 379 380 381 ``````/// \brief The \c IOService class is a wrapper for the ASIO \c io_service /// class. /// /// Currently, the interface of this class is very specific to the /// authoritative server implementation as indicated in the signature of /// the constructor, but the plan is to generalize it so that other BIND 10 /// modules can use this interface, too. `````` JINMEI Tatuya committed May 27, 2010 382 ``````class IOService { `````` JINMEI Tatuya committed Jun 21, 2010 383 384 385 `````` /// /// \name Constructors and Destructor /// `````` JINMEI Tatuya committed Jul 10, 2010 386 387 388 `````` /// These are currently very specific to the authoritative server /// implementation. /// `````` JINMEI Tatuya committed Jun 21, 2010 389 390 391 `````` /// Note: The copy constructor and the assignment operator are /// intentionally defined as private, making this class non-copyable. //@{ `````` JINMEI Tatuya committed Jun 20, 2010 392 393 394 ``````private: IOService(const IOService& source); IOService& operator=(const IOService& source); `````` JINMEI Tatuya committed May 27, 2010 395 ``````public: `````` JINMEI Tatuya committed Jul 10, 2010 396 397 398 399 400 401 402 403 404 `````` /// \brief The constructor with a specific IP address and port on which /// the services listen on. IOService(AuthSrv* auth_server, const char& port, const char& address); /// \brief The constructor with a specific port on which the services /// listen on. /// /// It effectively listens on "any" IPv4 and/or IPv6 addresses. /// IPv4/IPv6 services will be available if and only if \c use_ipv4 /// or \c use_ipv6 is \c true, respectively. `````` JINMEI Tatuya committed Jul 10, 2010 405 406 `````` IOService(AuthSrv* auth_server, const char& port, const bool use_ipv4, const bool use_ipv6); `````` JINMEI Tatuya committed Jun 21, 2010 407 `````` /// \brief The destructor. `````` JINMEI Tatuya committed May 27, 2010 408 `````` ~IOService(); `````` JINMEI Tatuya committed Jun 21, 2010 409 `````` //@} `````` JINMEI Tatuya committed Jun 22, 2010 410 411 412 `````` /// \brief Start the underlying event loop. /// `````` Evan Hunt committed Jul 20, 2010 413 414 `````` /// This method does not return control to the caller until /// the \c stop() method is called via some handler. `````` JINMEI Tatuya committed May 27, 2010 415 `````` void run(); `````` JINMEI Tatuya committed Jun 22, 2010 416 417 418 419 `````` /// \brief Stop the underlying event loop. /// /// This will return the control to the caller of the \c run() method. `````` JINMEI Tatuya committed May 27, 2010 420 `````` void stop(); `````` JINMEI Tatuya committed Jun 22, 2010 421 422 423 424 `````` /// \brief Return the native \c io_service object used in this wrapper. /// /// This is a short term work around to support other BIND 10 modules `````` JINMEI Tatuya committed Jul 21, 2010 425 `````` /// that share the same \c io_service with the authoritative server. `````` JINMEI Tatuya committed Jun 22, 2010 426 427 `````` /// It will eventually be removed once the wrapper interface is /// generalized. `````` Jelte Jansen committed May 31, 2010 428 `````` asio::io_service& get_io_service(); `````` JINMEI Tatuya committed Jun 22, 2010 429 430 431 432 433 434 435 436 437 438 439 440 `````` /// \brief A functor(-like) class that specifies a custom call back /// invoked from the event loop instead of the embedded authoritative /// server callbacks. /// /// Currently, the callback is intended to be used only for testing /// purposes. But we'll need a generic callback type like this to /// generalize the wrapper interface. typedef boost::function IOCallBack; /// \brief Set the custom call back invoked from the event loop. /// `````` JINMEI Tatuya committed Jun 20, 2010 441 442 443 `````` /// Right now this method is only for testing, but will eventually be /// generalized. void setCallBack(IOCallBack callback); `````` JINMEI Tatuya committed May 27, 2010 444 445 446 447 448 449 450 451 452 ``````private: IOServiceImpl* impl_; }; } // asio_link #endif // __ASIO_LINK_H // Local Variables: // mode: c++ // End: ``````