Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Kea
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
Operations
Operations
Incidents
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Sebastian Schrader
Kea
Commits
9739cbce
Commit
9739cbce
authored
Feb 23, 2011
by
Stephen Morris
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'trac554'
parents
955a1552
da6a33e3
Changes
36
Hide whitespace changes
Inline
Side-by-side
Showing
36 changed files
with
2137 additions
and
316 deletions
+2137
-316
src/lib/asiolink/Makefile.am
src/lib/asiolink/Makefile.am
+18
-14
src/lib/asiolink/README
src/lib/asiolink/README
+80
-1
src/lib/asiolink/asiolink.h
src/lib/asiolink/asiolink.h
+1
-14
src/lib/asiolink/dns_service.cc
src/lib/asiolink/dns_service.cc
+9
-7
src/lib/asiolink/dns_service.h
src/lib/asiolink/dns_service.h
+6
-0
src/lib/asiolink/dummy_io_cb.h
src/lib/asiolink/dummy_io_cb.h
+51
-0
src/lib/asiolink/internal/iofetch.h
src/lib/asiolink/internal/iofetch.h
+57
-20
src/lib/asiolink/interval_timer.cc
src/lib/asiolink/interval_timer.cc
+5
-5
src/lib/asiolink/io_address.cc
src/lib/asiolink/io_address.cc
+4
-1
src/lib/asiolink/io_address.h
src/lib/asiolink/io_address.h
+3
-3
src/lib/asiolink/io_asio_socket.h
src/lib/asiolink/io_asio_socket.h
+309
-0
src/lib/asiolink/io_endpoint.cc
src/lib/asiolink/io_endpoint.cc
+2
-1
src/lib/asiolink/io_endpoint.h
src/lib/asiolink/io_endpoint.h
+3
-3
src/lib/asiolink/io_error.h
src/lib/asiolink/io_error.h
+35
-0
src/lib/asiolink/io_fetch.cc
src/lib/asiolink/io_fetch.cc
+193
-0
src/lib/asiolink/io_fetch.h
src/lib/asiolink/io_fetch.h
+226
-0
src/lib/asiolink/io_message.h
src/lib/asiolink/io_message.h
+4
-3
src/lib/asiolink/io_service.cc
src/lib/asiolink/io_service.cc
+5
-4
src/lib/asiolink/io_socket.h
src/lib/asiolink/io_socket.h
+4
-7
src/lib/asiolink/recursive_query.cc
src/lib/asiolink/recursive_query.cc
+25
-25
src/lib/asiolink/tcp_server.cc
src/lib/asiolink/tcp_server.cc
+14
-7
src/lib/asiolink/tcp_socket.h
src/lib/asiolink/tcp_socket.h
+241
-16
src/lib/asiolink/tests/Makefile.am
src/lib/asiolink/tests/Makefile.am
+14
-8
src/lib/asiolink/tests/interval_timer_unittest.cc
src/lib/asiolink/tests/interval_timer_unittest.cc
+1
-0
src/lib/asiolink/tests/io_address_unittest.cc
src/lib/asiolink/tests/io_address_unittest.cc
+7
-1
src/lib/asiolink/tests/io_endpoint_unittest.cc
src/lib/asiolink/tests/io_endpoint_unittest.cc
+2
-1
src/lib/asiolink/tests/io_fetch_unittest.cc
src/lib/asiolink/tests/io_fetch_unittest.cc
+188
-0
src/lib/asiolink/tests/io_service_unittest.cc
src/lib/asiolink/tests/io_service_unittest.cc
+1
-0
src/lib/asiolink/tests/io_socket_unittest.cc
src/lib/asiolink/tests/io_socket_unittest.cc
+4
-1
src/lib/asiolink/tests/recursive_query_unittest.cc
src/lib/asiolink/tests/recursive_query_unittest.cc
+6
-1
src/lib/asiolink/tests/udp_endpoint_unittest.cc
src/lib/asiolink/tests/udp_endpoint_unittest.cc
+55
-0
src/lib/asiolink/tests/udp_query_unittest.cc
src/lib/asiolink/tests/udp_query_unittest.cc
+0
-145
src/lib/asiolink/tests/udp_socket_unittest.cc
src/lib/asiolink/tests/udp_socket_unittest.cc
+287
-0
src/lib/asiolink/udp_endpoint.h
src/lib/asiolink/udp_endpoint.h
+21
-8
src/lib/asiolink/udp_server.cc
src/lib/asiolink/udp_server.cc
+17
-9
src/lib/asiolink/udp_socket.h
src/lib/asiolink/udp_socket.h
+239
-11
No files found.
src/lib/asiolink/Makefile.am
View file @
9739cbce
...
...
@@ -12,24 +12,28 @@ CLEANFILES = *.gcno *.gcda
# have some code fragments that would hit gcc's unused-parameter warning,
# which would make the build fail with -Werror (our default setting).
lib_LTLIBRARIES
=
libasiolink.la
libasiolink_la_SOURCES
=
asiolink.h
libasiolink_la_SOURCES
+=
io_service.cc io_service.h
libasiolink_la_SOURCES
+=
dns_service.cc dns_service.h
libasiolink_la_SOURCES
+=
dns_server.h
libasiolink_la_SOURCES
+=
dns_lookup.h
libasiolink_la_SOURCES
=
asiolink.h
libasiolink_la_SOURCES
+=
dns_answer.h
libasiolink_la_SOURCES
+=
simple_callback.h
libasiolink_la_SOURCES
+=
dns_lookup.h
libasiolink_la_SOURCES
+=
dns_server.h
libasiolink_la_SOURCES
+=
dns_service.h dns_service.cc
libasiolink_la_SOURCES
+=
dummy_io_cb.h
libasiolink_la_SOURCES
+=
interval_timer.h interval_timer.cc
libasiolink_la_SOURCES
+=
recursive_query.h recursive_query.cc
libasiolink_la_SOURCES
+=
io_socket.cc io_socket.h
libasiolink_la_SOURCES
+=
io_address.h io_address.cc
libasiolink_la_SOURCES
+=
io_endpoint.h io_endpoint.cc
libasiolink_la_SOURCES
+=
io_error.h
libasiolink_la_SOURCES
+=
io_fetch.h io_fetch.cc
libasiolink_la_SOURCES
+=
io_message.h
libasiolink_la_SOURCES
+=
io_address.cc io_address.h
libasiolink_la_SOURCES
+=
io_endpoint.cc io_endpoint.h
libasiolink_la_SOURCES
+=
udp_endpoint.h udp_socket.h
libasiolink_la_SOURCES
+=
udp_server.h udp_server.cc
libasiolink_la_SOURCES
+=
udp_query.h udp_query.cc
libasiolink_la_SOURCES
+=
tcp_endpoint.h tcp_socket.h
libasiolink_la_SOURCES
+=
io_service.h io_service.cc
libasiolink_la_SOURCES
+=
io_socket.h io_socket.cc
libasiolink_la_SOURCES
+=
recursive_query.h recursive_query.cc
libasiolink_la_SOURCES
+=
simple_callback.h
libasiolink_la_SOURCES
+=
tcp_endpoint.h
libasiolink_la_SOURCES
+=
tcp_server.h tcp_server.cc
libasiolink_la_SOURCES
+=
tcp_socket.h
libasiolink_la_SOURCES
+=
udp_endpoint.h
libasiolink_la_SOURCES
+=
udp_server.h udp_server.cc
libasiolink_la_SOURCES
+=
udp_socket.h
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
# B10_CXXFLAGS)
libasiolink_la_CXXFLAGS
=
$(AM_CXXFLAGS)
...
...
src/lib/asiolink/README
View file @
9739cbce
...
...
@@ -33,7 +33,7 @@ This is intended to simplify development a bit, since it allows the
routines to be written in a straightfowrard step-step-step fashion rather
than as a complex chain of separate handler functions.
Coroutine objects (i.e., UDPServer, TCPServer and
UDPQuery
) are objects
Coroutine objects (i.e., UDPServer, TCPServer and
IOFetch
) are objects
with reenterable operator() members. When an instance of one of these
classes is called as a function, it resumes at the position where it left
off. Thus, a UDPServer can issue an asynchronous I/O call and specify
...
...
@@ -101,3 +101,82 @@ when the answer has arrived. In simplified form, the DNSQuery routine is:
Currently, DNSQuery is only implemented for UDP queries. In future work
it will be necessary to write code to fall back to TCP when circumstances
require it.
Upstream Fetches
================
Upstream fetches (queries by the resolver on behalf of a client) are made
using a slightly-modified version of the pattern described above.
Sockets
-------
First, it will be useful to understand the class hierarchy used in the
fetch logic:
IOSocket
|
IOAsioSocket
|
+-----+-----+
| |
UDPSocket TCPSocket
IOSocket is a wrapper class for a socket and is used by the authoritative
server code. It is an abstract base class, providing little more that the ability to hold the socket and to return the protocol in use.
Built on this is IOAsioSocket, which adds the open, close, asyncSend and
asyncReceive methods. This is a template class, which takes as template
argument the class of the object that will be used as the callback when the
asynchronous operation completes. This object can be of any type, but must
include an operator() method with the signature:
operator()(asio::error_code ec, size_t length)
... the two arguments being the status of the completed I/O operation and
the number of bytes transferred. (In the case of the open method, the second
argument will be zero.)
Finally, the TCPSocket and UDPSocket classes provide the body of the
asynchronous operations.
Fetch Sequence
--------------
The fetch is implemented by the IOFetch class, which takes as argument the
protocol to use. The sequence is:
REENTER:
render the question into a wire-format query packet
open() // Open socket and optionally connect
if (! synchronous) {
YIELD;
}
YIELD asyncSend(query) // Send query
do {
YIELD asyncReceive(response) // Read response
} while (! complete(response))
close() // Drop connection and close socket
server->resume
The open() method opens a socket for use. On TCP, it also makes a
connection to the remote end. So under UDP the operation will complete
immediately, but under TCP it could take a long time. One solution would be
for the open operation to post an event to the I/O queue; then both cases
could be regarded as being equivalent, with the completion being signalled
by the posting of the completion event. However UDP is the most common case
and that would involve extra overhead. So the open() returns a status
indicating whether the operation completed asynchronously. If it did, the
code yields back to the coroutine; if not the yield is bypassed.
The asynchronous send is straightforward, invoking the underlying ASIO
function. (Note that the address/port is supplied to both the open() and
asyncSend() methods - it is used by the TCPSocket in open() and by the
UDPSocket in asyncSend().)
The asyncReceive() method issues an asynchronous read and waits for completion.
The fetch object keeps track of the amount of data received so far and when
the receive completes it calls a method on the socket to determine if the
entire message has been received. (This will always be the case for UDP. On
TCP though, the message is preceded by a count field as several reads may be
required to read all the data.) The fetch loops until all the data is read.
Finally, the socket is closed and the server called to resume operation.
src/lib/asiolink/asiolink.h
View file @
9739cbce
...
...
@@ -32,6 +32,7 @@
#include <asiolink/io_endpoint.h>
#include <asiolink/io_message.h>
#include <asiolink/io_socket.h>
#include <asiolink/io_error.h>
/// \namespace asiolink
/// \brief A wrapper interface for the ASIO library.
...
...
@@ -83,20 +84,6 @@
/// the placeholder of callback handlers:
/// http://think-async.com/Asio/asio-1.3.1/doc/asio/reference/asio_handler_allocate.html
namespace
asiolink
{
/// \brief An exception that is thrown if an error occurs within the IO
/// 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
)
{}
};
}
// asiolink
#endif // __ASIOLINK_H
// Local Variables:
...
...
src/lib/asiolink/dns_service.cc
View file @
9739cbce
...
...
@@ -12,21 +12,23 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h> // for some IPC/network system calls
#include <boost/lexical_cast.hpp>
#include <config.h>
// unistd is needed for asio.hpp with SunStudio
#include <unistd.h>
#include <log/dummylog.h>
#include <asio.hpp>
#include <asiolink/dns_service.h>
#include <asiolink/io_service.h>
#include <asiolink/io_service.h>
#include <asiolink/tcp_server.h>
#include <asiolink/udp_server.h>
#include <log/dummylog.h>
#include <boost/lexical_cast.hpp>
using
isc
::
log
::
dlog
;
namespace
asiolink
{
...
...
src/lib/asiolink/dns_service.h
View file @
9739cbce
...
...
@@ -97,6 +97,12 @@ public:
/// It will eventually be removed once the wrapper interface is
/// generalized.
asio
::
io_service
&
get_io_service
()
{
return
io_service_
.
get_io_service
();
}
/// \brief Return the IO Service Object
///
/// \return IOService object for this DNS service.
asiolink
::
IOService
&
getIOService
()
{
return
(
io_service_
);}
private:
DNSServiceImpl
*
impl_
;
IOService
&
io_service_
;
...
...
src/lib/asiolink/dummy_io_cb.h
0 → 100644
View file @
9739cbce
// Copyright (C) 2011 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.
#ifndef __DUMMY_IO_CB_H
#define __DUMMY_IO_CB_H
#include <iostream>
#include <asio/error.hpp>
#include <asio/error_code.hpp>
namespace
asiolink
{
/// \brief Asynchronous I/O Completion Callback
///
/// The two socket classes (UDPSocket and TCPSocket) require that the I/O
/// completion callback function have an operator() method with the appropriate
/// signature. The classes are templates, any class with that method and
/// signature can be passed as the callback object - there is no need for a
/// base class defining the interface. However, some users of the socket
/// classes do not use the asynchronous I/O operations, yet have to supply a
/// template parameter. This is the reason for this class - it is the dummy
/// template parameter.
class
DummyIOCallback
{
public:
/// \brief Asynchronous I/O callback method
///
/// \param error Unused
/// \param length Unused
void
operator
()(
asio
::
error_code
,
size_t
)
{
// TODO: log an error if this method ever gets called.
}
};
}
// namespace asiolink
#endif // __DUMMY_IO_CB_H
src/lib/asiolink/
udp_query
.h
→
src/lib/asiolink/
internal/iofetch
.h
View file @
9739cbce
// Copyright (C) 201
1
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 201
0
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
...
...
@@ -12,26 +12,34 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __
UDP_QUERY
_H
#define __
UDP_QUERY
_H 1
#ifndef __
IOFETCH
_H
#define __
IOFETCH
_H 1
#ifndef ASIO_HPP
#error "asio.hpp must be included before including this, see asiolink.h as to why"
#endif
#include <config.h>
#include <asio.hpp>
#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <asiolink/
io_address
.h>
#include <coroutine.h>
#include <asiolink/
asiolink
.h>
#include <
asiolink/internal/
coroutine.h>
namespace
asiolink
{
// This file contains TCP/UDP-specific implementations of generic classes
// defined in asiolink.h. It is *not* intended to be part of the public
// API.
namespace
asiolink
{
//
// Asynchronous UDP
coroutine for upstream queri
es
// Asynchronous UDP
/TCP coroutine for upstream fetch
es
//
class
UDPQuery
:
public
coroutine
{
//class IOFetch : public coroutine, public UdpFetch, public TcpFetch {
class
IOFetch
:
public
coroutine
{
public:
// TODO Maybe this should be more generic than just for
UDPQuery
?
// TODO Maybe this should be more generic than just for
IOFetch
?
///
/// \brief Result of the query
///
...
...
@@ -43,12 +51,12 @@ public:
TIME_OUT
,
STOPPED
};
/// Abstract callback for the
UDPQuery
.
/// Abstract callback for the
IOFetch
.
class
Callback
{
public:
virtual
~
Callback
()
{}
/// This will be called when the
UDPQuery
is completed
/// This will be called when the
IOFetch
is completed
virtual
void
operator
()(
Result
result
)
=
0
;
};
///
...
...
@@ -59,11 +67,12 @@ public:
/// delete it if allocated on heap.
///@param timeout in ms.
///
explicit
UDPQuery
(
asio
::
io_service
&
io_service
,
IOFetch
(
asio
::
io_service
&
io_service
,
const
isc
::
dns
::
Question
&
q
,
const
IOAddress
&
addr
,
uint16_t
port
,
isc
::
dns
::
OutputBufferPtr
buffer
,
Callback
*
callback
,
int
timeout
=
-
1
);
Callback
*
callback
,
int
timeout
=
-
1
,
int
protocol
=
IPPROTO_UDP
);
void
operator
()(
asio
::
error_code
ec
=
asio
::
error_code
(),
size_t
length
=
0
);
/// Terminate the query.
...
...
@@ -80,9 +89,37 @@ private:
/// to many async_*() functions) and we want keep the same data. Some of
/// the data is not copyable too.
///
struct
PrivateData
;
boost
::
shared_ptr
<
PrivateData
>
data_
;
//struct IOFetchProtocol;
//boost::shared_ptr<IOFetchProtocol> data_;
//struct UdpData;
//struct TcpData;
boost
::
shared_ptr
<
UdpFetch
>
data_
;
boost
::
shared_ptr
<
TcpFetch
>
tcp_data_
;
};
class
UdpFetch
:
public
IOFetch
{
public:
struct
UdpData
;
explicit
UdpFetch
(
asio
::
io_service
&
io_service
,
const
isc
::
dns
::
Question
&
q
,
const
IOAddress
&
addr
,
uint16_t
port
,
isc
::
dns
::
OutputBufferPtr
buffer
,
IOFetch
::
Callback
*
callback
,
int
timeout
);
};
class
TcpFetch
:
public
IOFetch
{
public:
struct
TcpData
;
explicit
TcpFetch
(
io_service
&
io_service
,
const
Question
&
q
,
const
IOAddress
&
addr
,
uint16_t
port
,
OutputBufferPtr
buffer
,
Callback
*
callback
,
int
timeout
);
};
}
#endif // __IOFETCH_H
}
// namespace asiolink
#endif // __UDP_QUERY_H
// Local Variables:
// mode: c++
// End:
src/lib/asiolink/interval_timer.cc
View file @
9739cbce
...
...
@@ -14,18 +14,18 @@
#include <config.h>
// unistd is needed for asio.hpp with SunStudio
#include <unistd.h>
#include <unistd.h> // for some IPC/network system calls
#include <sys/socket.h>
#include <netinet/in.h>
#include <
asio
.hpp>
#include <
boost/bind
.hpp>
#include <exceptions/exceptions.h>
#include <asio.hpp>
#include <asiolink/interval_timer.h>
#include <asiolink/io_service.h>
#include <boost/bind.hpp>
namespace
asiolink
{
class
IntervalTimerImpl
{
...
...
src/lib/asiolink/io_address.cc
View file @
9739cbce
...
...
@@ -20,7 +20,10 @@
#include <asio.hpp>
#include <asiolink/asiolink.h>
#include <exceptions/exceptions.h>
#include <asiolink/io_address.h>
#include <asiolink/io_error.h>
using
namespace
asio
;
using
asio
::
ip
::
udp
;
...
...
src/lib/asiolink/io_address.h
View file @
9739cbce
...
...
@@ -12,8 +12,8 @@
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef __IOADDRESS_H
#define __IOADDRESS_H 1
#ifndef __IO
_
ADDRESS_H
#define __IO
_
ADDRESS_H 1
// IMPORTANT NOTE: only very few ASIO headers files can be included in
// this file. In particular, asio.hpp should never be included here.
...
...
@@ -120,7 +120,7 @@ private:
};
}
// asiolink
#endif // __IOADDRESS_H
#endif // __IO
_
ADDRESS_H
// Local Variables:
// mode: c++
...
...
src/lib/asiolink/io_asio_socket.h
0 → 100644
View file @
9739cbce
// 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.
#ifndef __IO_ASIO_SOCKET_H
#define __IO_ASIO_SOCKET_H 1
// IMPORTANT NOTE: only very few ASIO headers files can be included in
// this file. In particular, asio.hpp should never be included here.
// See the description of the namespace below.
#include <unistd.h> // for some network system calls
#include <functional>
#include <string>
#include <exceptions/exceptions.h>
#include <coroutine.h>
#include <asiolink/io_error.h>
#include <asiolink/io_socket.h>
namespace
asiolink
{
/// \brief Socket not open
///
/// Thrown on an attempt to do read/write to a socket that is not open.
class
SocketNotOpen
:
public
IOError
{
public:
SocketNotOpen
(
const
char
*
file
,
size_t
line
,
const
char
*
what
)
:
IOError
(
file
,
line
,
what
)
{}
};
/// Forward declaration of an IOEndpoint
class
IOEndpoint
;
/// \brief I/O Socket with asynchronous operations
///
/// This class is a wrapper for the ASIO socket classes such as
/// \c ip::tcp::socket and \c ip::udp::socket.
///
/// This is the basic IOSocket with additional operations - open, send, receive
/// and close. Depending on how the asiolink code develops, it may be a
/// temporary class: its main use is to add the template parameter needed for
/// the derived classes UDPSocket and TCPSocket but without changing the
/// signature of the more basic IOSocket class.
///
/// 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).
///
/// TODO: Check if IOAsioSocket class is still needed
///
/// \param C Template parameter identifying type of the callback object.
template
<
typename
C
>
class
IOAsioSocket
:
public
IOSocket
{
///
/// \name Constructors and Destructor
///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private, making this class non-copyable.
//@{
private:
IOAsioSocket
(
const
IOAsioSocket
<
C
>&
source
);
IOAsioSocket
&
operator
=
(
const
IOAsioSocket
<
C
>&
source
);
protected:
/// \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).
IOAsioSocket
()
{}
public:
/// The destructor.
virtual
~
IOAsioSocket
()
{}
//@}
/// \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
/// can change the internal state of the socket (consider the
/// 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.
virtual
int
getNative
()
const
=
0
;
/// \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
virtual
int
getProtocol
()
const
=
0
;
/// \brief Open AsioSocket
///
/// Opens the socket for asynchronous I/O. On a UDP socket, this is merely
/// an "open()" on the underlying socket (so completes immediately), but on
/// a TCP socket it also connects to the remote end (which is done as an
/// asynchronous operation).
///
/// For TCP, signalling of the completion of the operation is done by
/// by calling the callback function in the normal way. This could be done
/// for UDP (by posting en event on the event queue); however, that will
/// incur additional overhead in the most common case. Instead, the return
/// value indicates whether the operation was asynchronous or not. If yes,
/// (i.e. TCP) the callback has been posted to the event queue: if no (UDP),
/// no callback has been posted (in which case it is up to the caller as to
/// whether they want to manually post the callback themself.)
///
/// \param endpoint Pointer to the endpoint object. This is ignored for
/// a UDP socket (the target is specified in the send call), but should
/// be of type TCPEndpoint for a TCP connection.
/// \param callback I/O Completion callback, called when the operation has
/// completed, but only if the operation was asynchronous.
///
/// \return true if an asynchronous operation was started and the caller
/// should yield and wait for completion, false if the operation was
/// completed synchronously and no callback was queued.
virtual
bool
open
(
const
IOEndpoint
*
endpoint
,
C
&
callback
)
=
0
;
/// \brief Send Asynchronously
///
/// This corresponds to async_send_to() for UDP sockets and async_send()
/// for TCP. In both cases an endpoint argument is supplied indicating the
/// target of the send - this is ignored for TCP.
///
/// \param data Data to send
/// \param length Length of data to send
/// \param endpoint Target of the send
/// \param callback Callback object.
virtual
void
asyncSend
(
const
void
*
data
,
size_t
length
,
const
IOEndpoint
*
endpoint
,
C
&
callback
)
=
0
;
/// \brief Receive Asynchronously
///
/// This correstponds to async_receive_from() for UDP sockets and
/// async_receive() for TCP. In both cases, an endpoint argument is
/// supplied to receive the source of the communication. For TCP it will
/// be filled in with details of the connection.
///
/// \param data Buffer to receive incoming message
/// \param length Length of the data buffer
/// \param cumulative Amount of data that should already be in the buffer.
/// \param endpoint Source of the communication
/// \param callback Callback object
virtual
void
asyncReceive
(
void
*
data
,
size_t
length
,
size_t
cumulative
,
IOEndpoint
*
endpoint
,
C
&
callback
)
=
0
;
/// \brief Checks if the data received is complete.
///
/// This applies to TCP receives, where the data is a byte stream and a
/// receive is not guaranteed to receive the entire message. DNS messages
/// over TCP are prefixed by a two-byte count field. This method takes the
/// amount received so far and the amount received in this I/O and checks
/// if the message is complete, returning the appropriate indication. As
/// a side-effect, it also updates the amount received.
///
/// For a UDP receive, all the data is received in one I/O, so this is
/// effectively a no-op (although it does update the amount received).
///
/// \param data Data buffer containing data to date
/// \param length Amount of data received in last asynchronous I/O
/// \param cumulative On input, amount of data received before the last
/// I/O. On output, the total amount of data received to date.
///
/// \return true if the receive is complete, false if another receive is
/// needed.
virtual
bool
receiveComplete
(
void
*
data
,
size_t
length
,
size_t
&
cumulative
)
=
0
;
/// \brief Cancel I/O On AsioSocket
virtual
void
cancel
()
=
0
;
/// \brief Close socket