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
682436e8
Commit
682436e8
authored
Feb 28, 2011
by
Stephen Morris
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[trac499] Completed TCPSocket and unit tests
parent
b13c2fd0
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
546 additions
and
265 deletions
+546
-265
src/lib/asiolink/Makefile.am
src/lib/asiolink/Makefile.am
+1
-0
src/lib/asiolink/asiolink_utilities.h
src/lib/asiolink/asiolink_utilities.h
+61
-0
src/lib/asiolink/io_asio_socket.h
src/lib/asiolink/io_asio_socket.h
+37
-44
src/lib/asiolink/io_fetch.cc
src/lib/asiolink/io_fetch.cc
+2
-1
src/lib/asiolink/tcp_socket.h
src/lib/asiolink/tcp_socket.h
+71
-40
src/lib/asiolink/tests/Makefile.am
src/lib/asiolink/tests/Makefile.am
+1
-0
src/lib/asiolink/tests/asiolink_utilities_unittest.cc
src/lib/asiolink/tests/asiolink_utilities_unittest.cc
+74
-0
src/lib/asiolink/tests/tcp_socket_unittest.cc
src/lib/asiolink/tests/tcp_socket_unittest.cc
+267
-145
src/lib/asiolink/tests/udp_socket_unittest.cc
src/lib/asiolink/tests/udp_socket_unittest.cc
+2
-2
src/lib/asiolink/udp_socket.h
src/lib/asiolink/udp_socket.h
+30
-33
No files found.
src/lib/asiolink/Makefile.am
View file @
682436e8
...
...
@@ -13,6 +13,7 @@ CLEANFILES = *.gcno *.gcda
# which would make the build fail with -Werror (our default setting).
lib_LTLIBRARIES
=
libasiolink.la
libasiolink_la_SOURCES
=
asiolink.h
libasiolink_la_SOURCES
+=
asiolink_utilities.h
libasiolink_la_SOURCES
+=
asiodef.cc asiodef.h
libasiolink_la_SOURCES
+=
dns_answer.h
libasiolink_la_SOURCES
+=
dns_lookup.h
...
...
src/lib/asiolink/asiolink_utilities.h
0 → 100644
View file @
682436e8
// 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 __ASIOLINK_UTILITIES_H
#define __ASIOLINK_UTILITIES_H
#include <cstddef>
namespace
asiolink
{
/// \brief Read Unsigned 16-Bit Integer from Buffer
///
/// This is essentially a copy of the isc::dns::InputBuffer::readUint16. It
/// should really be moved into a separate library.
///
/// \param buffer Data buffer at least two bytes long of which the first two
/// bytes are assumed to represent a 16-bit integer in network-byte
/// order.
///
/// \return Value of 16-bit integer
inline
uint16_t
readUint16
(
const
void
*
buffer
)
{
const
uint8_t
*
byte_buffer
=
static_cast
<
const
uint8_t
*>
(
buffer
);
uint16_t
result
=
(
static_cast
<
uint16_t
>
(
byte_buffer
[
0
]))
<<
8
;
result
|=
static_cast
<
uint16_t
>
(
byte_buffer
[
1
]);
return
(
result
);
}
/// \brief Write Unisgned 16-Bit Integer to Buffer
///
/// This is essentially a copy of isc::dns::OutputBuffer::writeUint16. It
/// should really be moved into a separate library.
///
/// \param value 16-bit value to convert
/// \param buffer Data buffer at least two bytes long into which the 16-bit
/// value is written in network-byte order.
inline
void
writeUint16
(
uint16_t
value
,
void
*
buffer
)
{
uint8_t
*
byte_buffer
=
static_cast
<
uint8_t
*>
(
buffer
);
byte_buffer
[
0
]
=
static_cast
<
uint8_t
>
((
value
&
0xff00U
)
>>
8
);
byte_buffer
[
1
]
=
static_cast
<
uint8_t
>
(
value
&
0x00ffU
);
}
}
// namespace asiolink
#endif // __ASIOLINK_UTILITIES_H
src/lib/asiolink/io_asio_socket.h
View file @
682436e8
...
...
@@ -41,7 +41,7 @@ public:
IOError
(
file
,
line
,
what
)
{}
};
/// \brief
Socket not open
/// \brief
Error setting socket options
///
/// Thrown if attempt to change socket options fails.
class
SocketSetError
:
public
IOError
{
...
...
@@ -50,7 +50,7 @@ public:
IOError
(
file
,
line
,
what
)
{}
};
/// \brief Buffer
O
verflow
/// \brief Buffer
o
verflow
///
/// Thrown if an attempt is made to receive into an area beyond the end of
/// the receive data buffer.
...
...
@@ -108,24 +108,23 @@ public:
/// \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 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
/// c
an 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
/// re
quires 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.
/// In general, the application should avoid using this method;
it
///
essentially discloses an implementation specific "handle" that can
/// c
hange the internal state of the socket (consider what would happen if
///
the application closes it, for example). But we sometimes need to
///
perform very low-level operations that requires the native
/// re
presentation. 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.
///
file descriptor for UNIX-like systems.
virtual
int
getNative
()
const
=
0
;
/// \brief Return the transport protocol of the socket.
...
...
@@ -135,16 +134,15 @@ public:
///
/// This method never throws an exception.
///
/// \return IPPROTO_UDP for UDP sockets
/// \return IPPROTO_TCP for TCP sockets
/// \return \c IPPROTO_UDP for UDP sockets, \c IPPROTO_TCP for TCP sockets
virtual
int
getProtocol
()
const
=
0
;
/// \brief Is Open() synchronous?
///
/// On a
UDP socket, an "open" operation is merely a call to "open()" on
///
the underlying socket (so completes immediately), but on a TCP socket it
/// a
lso includings connecting to the remote end (which is done as an
/// a
synchronous operation)
.
/// On a
TCP socket, an "open" operation is a call to the socket's "open()"
///
method followed by a connection to the remote system: it is an
/// a
synchronous operation. On a UDP socket, it is just a call to "open()"
/// a
nd completes synchronously
.
///
/// 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
...
...
@@ -154,31 +152,31 @@ public:
/// asynchronously.
///
/// Owing to the way that the stackless coroutines are implemented, we need
/// to know _before_ executing the
operation whether or not the open
is
/// asynchronous. So this method
simply provides
that information.
/// to know _before_ executing the
"open" function whether or not it
is
/// asynchronous. So this method
is called to provide
that information.
///
/// (The reason there is a need to know is because the call to open() passes
/// in the state of the coroutine at the time the call is made. On an
/// asynchronous I/O, we need to set the state to point to the statement
/// after the call to open()
before we pass the corot
uine to the open()
/// call. Unfortunately, the macros that
do this also yield control - which
///
we don't want to do if the open is synchronous. Hence we need to know
///
before we make the call to open() whether that call will complete
/// asynchronously.)
/// after the call to open()
_before_ we pass the coro
uine to the open()
/// call. Unfortunately, the macros that
set the state of the coroutine
///
also yield control - which we don't want to do if the open is
///
synchronous. Hence we need to know before we make the call to open()
///
whether that call will complete
asynchronously.)
virtual
bool
isOpenSynchronous
()
const
=
0
;
/// \brief Open AsioSocket
///
/// Opens the socket for asynchronous I/O. The open will complete
/// synchronously on UCP or asynchronously on TCP (in which case a callback
/// will be queued): what will happen can be found by calling the method
/// isOpenSynchronous().
/// will be queued).
///
/// \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.
///
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.
/// completed, but only if the operation was asynchronous. (It is
/// ignored on a UDP socket.)
virtual
void
open
(
const
IOEndpoint
*
endpoint
,
C
&
callback
)
=
0
;
/// \brief Send Asynchronously
...
...
@@ -196,7 +194,7 @@ public:
/// \brief Receive Asynchronously
///
/// This corres
t
ponds to async_receive_from() for UDP sockets and
/// This corresponds 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.
...
...
@@ -214,22 +212,17 @@ public:
/// 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.
/// amount received so far and checks if the message is complete.
///
/// 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
).
/// effectively a no-op).
///
/// \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.
/// \param length Total amount of data in the buffer.
///
/// \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
;
/// needed.
virtual
bool
receiveComplete
(
const
void
*
data
,
size_t
length
)
=
0
;
/// \brief Cancel I/O On AsioSocket
virtual
void
cancel
()
=
0
;
...
...
src/lib/asiolink/io_fetch.cc
View file @
682436e8
...
...
@@ -222,8 +222,9 @@ IOFetch::operator()(asio::error_code ec, size_t length) {
CORO_YIELD
data_
->
socket
->
asyncReceive
(
data_
->
data
.
get
(),
static_cast
<
size_t
>
(
MIN_LENGTH
),
data_
->
cumulative
,
data_
->
remote
.
get
(),
*
this
);
data_
->
cumulative
+=
length
;
std
::
cerr
<<
"IOFetch: resuming after asynchronous receive
\n
"
;
}
while
(
!
data_
->
socket
->
receiveComplete
(
data_
->
data
.
get
(),
length
,
}
while
(
!
data_
->
socket
->
receiveComplete
(
data_
->
data
.
get
(),
data_
->
cumulative
));
// The message is not rendered yet, so we can't print it easily
...
...
src/lib/asiolink/tcp_socket.h
View file @
682436e8
...
...
@@ -24,7 +24,6 @@
#include <sys/socket.h>
#include <unistd.h> // for some IPC/network system calls
#include <iostream>
#include <cstddef>
#include <boost/bind.hpp>
...
...
@@ -34,6 +33,7 @@
#include <dns/buffer.h>
#include <asiolink/asiolink_utilities.h>
#include <asiolink/io_asio_socket.h>
#include <asiolink/io_endpoint.h>
#include <asiolink/io_service.h>
...
...
@@ -65,15 +65,15 @@ public:
/// \brief Constructor from an ASIO TCP socket.
///
/// \param socket The ASIO representation of the TCP socket. It
///
is assumed that the caller will open and close the socket, so
///
these
operations are a no-op for that socket.
/// \param socket The ASIO representation of the TCP socket. It
is assumed
///
that the caller will open and close the socket, so these
///
operations are a no-op for that socket.
TCPSocket
(
asio
::
ip
::
tcp
::
socket
&
socket
);
/// \brief Constructor
///
/// Used when the TCPSocket is being asked to manage its own internal
/// socket. I
t is assumed that open() and close() will not b
e used.
/// socket. I
n this case, the open() and close() methods ar
e used.
///
/// \param service I/O Service object used to manage the socket.
TCPSocket
(
IOService
&
service
);
...
...
@@ -100,10 +100,10 @@ public:
/// \brief Open Socket
///
/// Opens the
UD
P socket. This is an asynchronous operation, completion of
/// Opens the
TC
P socket. This is an asynchronous operation, completion of
/// which will be signalled via a call to the callback function.
///
/// \param endpoint Endpoint to which the socket will connect
to
.
/// \param endpoint Endpoint to which the socket will connect.
/// \param callback Callback object.
virtual
void
open
(
const
IOEndpoint
*
endpoint
,
C
&
callback
);
...
...
@@ -115,7 +115,8 @@ public:
///
/// \param data Data to send
/// \param length Length of data to send
/// \param endpoint Target of the send
/// \param endpoint Target of the send. (Unused for a TCP socket because
/// that was determined when the connection was opened.)
/// \param callback Callback object.
virtual
void
asyncSend
(
const
void
*
data
,
size_t
length
,
const
IOEndpoint
*
endpoint
,
C
&
callback
);
...
...
@@ -136,21 +137,15 @@ public:
/// \brief Checks if the data received is complete.
///
/// As all the data is received in one I/O, so this is, this is effectively
/// a no-op (although it does update the amount of data received).
/// Checks if all the data has been received by checking that the amount
/// of data received is equal to the number in the first two bytes of the
/// message plus two (for the count field itself).
///
/// \param data Data buffer containing data to date. (This is ignored
/// for TCP receives.)
/// \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.
/// \param data Data buffer containing data to date (ignored)
/// \param length Amount of data in the buffer.
///
/// \return true if the receive is complete, false if another receive is
/// needed.
virtual
bool
receiveComplete
(
void
*
,
size_t
length
,
size_t
&
cumulative
)
{
cumulative
=
length
;
return
(
true
);
}
/// \return true if the receive is complete, false if not.
virtual
bool
receiveComplete
(
const
void
*
data
,
size_t
length
);
/// \brief Cancel I/O On Socket
virtual
void
cancel
();
...
...
@@ -176,6 +171,10 @@ private:
// achieved by altering isc::dns::buffer to have pairs of methods:
// getLength()/getTCPLength(), getData()/getTCPData(), with the getTCPXxx()
// methods taking into account a two-byte count field.)
//
// The option of sending the data in two operations, the count followed by
// the data was discounted as that would lead to two callbacks which would
// cause problems with the stackless coroutine code.
isc
::
dns
::
OutputBufferPtr
send_buffer_
;
///< Send buffer
};
...
...
@@ -212,8 +211,6 @@ TCPSocket<C>::open(const IOEndpoint* endpoint, C& callback) {
// Ignore opens on already-open socket. Don't throw a failure because
// of uncertainties as to what precedes whan when using asynchronous I/O.
// At also allows us a treat a passed-in socket as a self-managed socket.
std
::
cerr
<<
"TCPSocket::open(): open_ flags is "
<<
isopen_
<<
"
\n
"
;
if
(
!
isopen_
)
{
if
(
endpoint
->
getFamily
()
==
AF_INET
)
{
socket_
.
open
(
asio
::
ip
::
tcp
::
v4
());
...
...
@@ -266,8 +263,6 @@ TCPSocket<C>::asyncSend(const void* data, size_t length, const IOEndpoint*,
send_buffer_
->
writeData
(
data
,
length
);
// ... and send it
std
::
cerr
<<
"TCPSocket::asyncSend(): sending "
<<
count
<<
" data bytes
\n
"
;
socket_
.
async_send
(
asio
::
buffer
(
send_buffer_
->
getData
(),
send_buffer_
->
getLength
()),
callback
);
}
catch
(
boost
::
numeric
::
bad_numeric_cast
&
e
)
{
...
...
@@ -281,34 +276,70 @@ TCPSocket<C>::asyncSend(const void* data, size_t length, const IOEndpoint*,
}
}
// Receive a message. Note that the "cumulative" argument is ignored - every TCP
// receive is put into the buffer beginning at the start - there is no concept
// receiving a subsequent part of a message. Same critera as before concerning
// the need for the socket to be open.
// Receive a message. Note that the "offset" argument is used as an index
// into the buffer in order to decide where to put the data. It is up to the
// caller to initialize the data to zero
template
<
typename
C
>
void
TCPSocket
<
C
>::
asyncReceive
(
void
*
data
,
size_t
length
,
size_t
,
TCPSocket
<
C
>::
asyncReceive
(
void
*
data
,
size_t
length
,
size_t
offset
,
IOEndpoint
*
endpoint
,
C
&
callback
)
{
if
(
isopen_
)
{
// Upconvert the endpoint again.
// Upconvert to a TCPEndpoint. We need to do this because although
// IOEndpoint is the base class of UDPEndpoint and TCPEndpoint, it
// does not contain a method for getting at the underlying endpoint
// type - that is in the derived class and the two classes differ on
// return type.
assert
(
endpoint
->
getProtocol
()
==
IPPROTO_TCP
);
const
TCPEndpoint
*
tcp_endpoint
=
static_cast
<
const
TCPEndpoint
*>
(
endpoint
);
std
::
cerr
<<
"TCPSocket::asyncReceive(): receiving from "
<<
tcp_endpoint
->
getAddress
().
toText
()
<<
", port "
<<
tcp_endpoint
->
getPort
()
<<
"
\n
"
;
// TODO: Complete TCPSocket::asyncReceive()
TCPEndpoint
*
tcp_endpoint
=
static_cast
<
TCPEndpoint
*>
(
endpoint
);
// Write the endpoint details from the comminications link. Ideally
// we should make IOEndpoint assignable, but this runs in to all sorts
// of problems concerning the management of the underlying Boost
// endpoint (e.g. if it is not self-managed, is the copied one
// self-managed?) The most pragmatic solution is to let Boost take care
// of everything and copy details of the underlying endpoint.
tcp_endpoint
->
getASIOEndpoint
()
=
socket_
.
remote_endpoint
();
// Ensure we can write into the buffer and if so, set the pointer to
// where the data will be written.
if
(
offset
>=
length
)
{
isc_throw
(
BufferOverflow
,
"attempt to read into area beyond end of "
"TCP receive buffer"
);
}
void
*
buffer_start
=
static_cast
<
void
*>
(
static_cast
<
uint8_t
*>
(
data
)
+
offset
);
// ... and kick off the read.
socket_
.
async_receive
(
asio
::
buffer
(
buffer_start
,
length
-
offset
),
callback
);
}
else
{
isc_throw
(
SocketNotOpen
,
"attempt to receive from a TCP socket that is not open"
);
}
}
// Is the receive complete?
template
<
typename
C
>
bool
TCPSocket
<
C
>::
receiveComplete
(
const
void
*
data
,
size_t
length
)
{
bool
complete
=
false
;
// If we have read at least two bytes, we can work out how much we should be
// reading.
if
(
length
>=
2
)
{
// Convert first two bytes to a count and check that the following data
// is that length.
// TODO: Should we check to see if we have received too much data?
uint16_t
expected
=
readUint16
(
data
);
complete
=
((
expected
+
2
)
==
length
);
}
return
(
complete
);
}
// Cancel I/O on the socket. No-op if the socket is not open.
template
<
typename
C
>
void
TCPSocket
<
C
>::
cancel
()
{
if
(
isopen_
)
{
...
...
src/lib/asiolink/tests/Makefile.am
View file @
682436e8
...
...
@@ -18,6 +18,7 @@ TESTS += run_unittests
run_unittests_SOURCES
=
run_unittests.cc
run_unittests_SOURCES
+=
$(top_srcdir)
/src/lib/dns/tests/unittest_util.h
run_unittests_SOURCES
+=
$(top_srcdir)
/src/lib/dns/tests/unittest_util.cc
run_unittests_SOURCES
+=
asiolink_utilities_unittest.cc
run_unittests_SOURCES
+=
io_address_unittest.cc
run_unittests_SOURCES
+=
io_endpoint_unittest.cc
run_unittests_SOURCES
+=
io_fetch_unittest.cc
...
...
src/lib/asiolink/tests/asiolink_utilities_unittest.cc
0 → 100644
View file @
682436e8
// 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.
/// \brief Test of asiolink utilties
///
/// Tests the fuctionality of the asiolink utilities code by comparing them
/// with the equivalent methods in isc::dns::[Input/Output]Buffer.
#include <cstddef>
#include <gtest/gtest.h>
#include <dns/buffer.h>
#include <asiolink/asiolink_utilities.h>
using
namespace
asiolink
;
using
namespace
isc
::
dns
;
TEST
(
asioutil
,
readUint16
)
{
// Reference buffer
uint8_t
data
[
2
];
isc
::
dns
::
InputBuffer
buffer
(
data
,
sizeof
(
data
));
// Avoid possible compiler warnings by only setting uint8_t variables to
// uint8_t values.
uint8_t
i8
=
0
;
uint8_t
j8
=
0
;
for
(
int
i
=
0
;
i
<
(
2
<<
8
);
++
i
,
++
i8
)
{
for
(
int
j
=
0
;
j
<
(
2
<<
8
);
++
j
,
++
j8
)
{
data
[
0
]
=
i8
;
data
[
1
]
=
j8
;
buffer
.
setPosition
(
0
);
EXPECT_EQ
(
buffer
.
readUint16
(),
readUint16
(
data
));
}
}
}
TEST
(
asioutil
,
writeUint16
)
{
// Reference buffer
isc
::
dns
::
OutputBuffer
buffer
(
2
);
uint8_t
test
[
2
];
// Avoid possible compiler warnings by only setting uint16_t variables to
// uint16_t values.
uint16_t
i16
=
0
;
for
(
uint32_t
i
=
0
;
i
<
(
2
<<
16
);
++
i
,
++
i16
)
{
// Write the reference data
buffer
.
clear
();
buffer
.
writeUint16
(
i16
);
// ... and the test data
writeUint16
(
i16
,
test
);
// ... and compare
const
uint8_t
*
ref
=
static_cast
<
const
uint8_t
*>
(
buffer
.
getData
());
EXPECT_EQ
(
ref
[
0
],
test
[
0
]);
EXPECT_EQ
(
ref
[
1
],
test
[
1
]);
}
}
src/lib/asiolink/tests/tcp_socket_unittest.cc
View file @
682436e8
This diff is collapsed.
Click to expand it.
src/lib/asiolink/tests/udp_socket_unittest.cc
View file @
682436e8
...
...
@@ -263,8 +263,8 @@ TEST(UDPSocket, SequenceTest) {
EXPECT_EQ
(
SERVER_PORT
,
client_remote_endpoint
.
getPort
());
// Finally, check that the receive received a complete buffer's worth of data.
EXPECT_TRUE
(
client
.
receiveComplete
(
&
data
[
0
],
client_cb
.
getLength
(),
client_cumulative
));
client_cumulative
+=
client_cb
.
getLength
();
EXPECT_TRUE
(
client
.
receiveComplete
(
&
data
[
0
],
client_cumulative
));
EXPECT_EQ
(
client_cb
.
getLength
(),
client_cumulative
);
// Close client and server.
...
...
src/lib/asiolink/udp_socket.h
View file @
682436e8
...
...
@@ -53,15 +53,15 @@ public:
/// \brief Constructor from an ASIO UDP socket.
///
/// \param socket The ASIO representation of the UDP socket. It
///
is assumed that the caller will open and close the socket, so
///
these
operations are a no-op for that socket.
/// \param socket The ASIO representation of the UDP socket. It
is assumed
///
that the caller will open and close the socket, so these
///
operations are a no-op for that socket.
UDPSocket
(
asio
::
ip
::
udp
::
socket
&
socket
);
/// \brief Constructor
///
/// Used when the UDPSocket is being asked to manage its own internal
/// socket. I
t is assumed that open() and close() will not b
e used.
/// socket. I
n this case, the open() and close() methods ar
e used.
///
/// \param service I/O Service object used to manage the socket.
UDPSocket
(
IOService
&
service
);
...
...
@@ -90,9 +90,11 @@ public:
///
/// Opens the UDP socket. This is a synchronous operation.
///
/// \param endpoint Endpoint to which the socket will connect to.
/// \param callback Unused.
virtual
void
open
(
const
IOEndpoint
*
endpoint
,
C
&
);
/// \param endpoint Endpoint to which the socket will send data. This is
/// used to determine the address family trhat should be used for the
/// underlying socket.
/// \param callback Unused as the operation is synchronous.
virtual
void
open
(
const
IOEndpoint
*
endpoint
,
C
&
callback
);
/// \brief Send Asynchronously
///
...
...
@@ -110,8 +112,8 @@ public:
/// \brief Receive Asynchronously
///
/// Calls the underlying socket's async_receive_from() method to read a
/// packet of data from a remote endpoint. Arrival of the data is
///
signalled
via a call to the callback function.
/// packet of data from a remote endpoint. Arrival of the data is
signalled
/// via a call to the callback function.
///
/// \param data Buffer to receive incoming message
/// \param length Length of the data buffer
...
...
@@ -123,19 +125,15 @@ public:
/// \brief Checks if the data received is complete.
///
/// As all the data is received in one I/O, so this is, this is effectively
/// a no-op (although it does update the amount of data received).
/// For a UDP socket all the data is received in one I/O, so this is
/// effectively a no-op (although it does update the amount of data
/// received).
///
/// \param data Data buffer containing data to date. (This is ignored
/// for UDP receives.)
/// \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.
/// \param data Data buffer containing data to date (ignored)
/// \param length Amount of data in the buffer.
///
/// \return true if the receive is complete, false if another receive is
/// needed. Always true for a UDP socket.
virtual
bool
receiveComplete
(
void
*
,
size_t
length
,
size_t
&
cumulative
)
{
cumulative
=
length
;
/// \return Always true
virtual
bool
receiveComplete
(
const
void
*
,
size_t
)
{
return
(
true
);
}
...
...
@@ -185,10 +183,11 @@ UDPSocket<C>::~UDPSocket()
template
<
typename
C
>
void
UDPSocket
<
C
>::
open
(
const
IOEndpoint
*
endpoint
,
C
&
)
{
// Ignore opens on already-open socket. Don't throw a failure because
// of uncertainties as to what precedes whan when using asynchronous I/O.
// At also allows us a treat a passed-in socket as a self-managed socket.
// Ignore opens on already-open socket. (Don't throw a failure because
// of uncertainties as to what precedes whan when using asynchronous I/O.)
// It also allows us a treat a passed-in socket in exactly the same way as
// a self-managed socket (in that we can call the open() and close() methods
// of this class).
if
(
!
isopen_
)
{
if
(
endpoint
->
getFamily
()
==
AF_INET
)
{
socket_
.
open
(
asio
::
ip
::
udp
::
v4
());
...
...
@@ -198,8 +197,7 @@ UDPSocket<C>::open(const IOEndpoint* endpoint, C&) {
}
isopen_
=
true
;
// Ensure it can send and receive 4K buffers.