Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
actor-incubator
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
actor-incubator
Commits
ce5a53ca
Commit
ce5a53ca
authored
Jul 27, 2020
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch to more lightweight socket API wrapper
parent
b20f0ad8
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
181 additions
and
191 deletions
+181
-191
libcaf_net/caf/net/pipe_socket.hpp
libcaf_net/caf/net/pipe_socket.hpp
+6
-8
libcaf_net/caf/net/socket.hpp
libcaf_net/caf/net/socket.hpp
+9
-1
libcaf_net/caf/net/stream_socket.hpp
libcaf_net/caf/net/stream_socket.hpp
+20
-18
libcaf_net/caf/net/stream_transport.hpp
libcaf_net/caf/net/stream_transport.hpp
+35
-31
libcaf_net/src/multiplexer.cpp
libcaf_net/src/multiplexer.cpp
+33
-36
libcaf_net/src/pipe_socket.cpp
libcaf_net/src/pipe_socket.cpp
+8
-15
libcaf_net/src/pollset_updater.cpp
libcaf_net/src/pollset_updater.cpp
+5
-5
libcaf_net/src/socket.cpp
libcaf_net/src/socket.cpp
+14
-0
libcaf_net/src/stream_socket.cpp
libcaf_net/src/stream_socket.cpp
+10
-36
libcaf_net/test/endpoint_manager.cpp
libcaf_net/test/endpoint_manager.cpp
+16
-13
libcaf_net/test/multiplexer.cpp
libcaf_net/test/multiplexer.cpp
+10
-11
libcaf_net/test/stream_application.cpp
libcaf_net/test/stream_application.cpp
+5
-11
libcaf_net/test/stream_socket.cpp
libcaf_net/test/stream_socket.cpp
+5
-3
libcaf_net/test/stream_transport.cpp
libcaf_net/test/stream_transport.cpp
+5
-3
No files found.
libcaf_net/caf/net/pipe_socket.hpp
View file @
ce5a53ca
...
...
@@ -27,6 +27,10 @@
#include "caf/net/socket.hpp"
#include "caf/net/socket_id.hpp"
// Note: This API mostly wraps platform-specific functions that return ssize_t.
// We return ptrdiff_t instead, since only POSIX defines ssize_t and the two
// types are functionally equivalent.
namespace
caf
::
net
{
/// A unidirectional communication endpoint for inter-process communication.
...
...
@@ -46,19 +50,13 @@ expected<std::pair<pipe_socket, pipe_socket>> CAF_NET_EXPORT make_pipe();
/// @param buf Memory region for reading the message to send.
/// @returns The number of written bytes on success, otherwise an error code.
/// @relates pipe_socket
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
write
(
pipe_socket
x
,
span
<
const
byte
>
buf
);
ptrdiff_t
CAF_NET_EXPORT
write
(
pipe_socket
x
,
span
<
const
byte
>
buf
);
/// Receives data from `x`.
/// @param x Connected endpoint.
/// @param buf Memory region for storing the received bytes.
/// @returns The number of received bytes on success, otherwise an error code.
/// @relates pipe_socket
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
read
(
pipe_socket
x
,
span
<
byte
>
buf
);
/// Converts the result from I/O operation on a ::pipe_socket to either an
/// error code or a non-zero positive integer.
/// @relates pipe_socket
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
check_pipe_socket_io_res
(
std
::
make_signed
<
size_t
>::
type
res
);
ptrdiff_t
CAF_NET_EXPORT
read
(
pipe_socket
x
,
span
<
byte
>
buf
);
}
// namespace caf::net
libcaf_net/caf/net/socket.hpp
View file @
ce5a53ca
...
...
@@ -69,7 +69,7 @@ To CAF_NET_EXPORT socket_cast(From x) {
return
To
{
x
.
id
};
}
/// Close socket `x`.
/// Close
s
socket `x`.
/// @relates socket
void
CAF_NET_EXPORT
close
(
socket
x
);
...
...
@@ -77,6 +77,14 @@ void CAF_NET_EXPORT close(socket x);
/// @relates socket
std
::
errc
CAF_NET_EXPORT
last_socket_error
();
/// Checks whether `last_socket_error()` would return an error code that
/// indicates a temporary error.
/// @returns `true` if `last_socket_error()` returned either
/// `std::errc::operation_would_block` or
/// `std::errc::resource_unavailable_try_again`, `false` otherwise.
/// @relates socket
bool
CAF_NET_EXPORT
last_socket_error_is_temporary
();
/// Returns the last socket error as human-readable string.
/// @relates socket
std
::
string
CAF_NET_EXPORT
last_socket_error_as_string
();
...
...
libcaf_net/caf/net/stream_socket.hpp
View file @
ce5a53ca
...
...
@@ -18,10 +18,16 @@
#pragma once
#include <cstddef>
#include "caf/detail/net_export.hpp"
#include "caf/fwd.hpp"
#include "caf/net/network_socket.hpp"
// Note: This API mostly wraps platform-specific functions that return ssize_t.
// We return ptrdiff_t instead, since only POSIX defines ssize_t and the two
// types are functionally equivalent.
namespace
caf
::
net
{
/// A connection-oriented network communication endpoint for bidirectional byte
...
...
@@ -47,37 +53,33 @@ error CAF_NET_EXPORT keepalive(stream_socket x, bool new_value);
error
CAF_NET_EXPORT
nodelay
(
stream_socket
x
,
bool
new_value
);
/// Receives data from `x`.
/// @param x
C
onnected endpoint.
/// @param x
A c
onnected endpoint.
/// @param buf Points to destination buffer.
/// @returns The number of received bytes on success, an error code otherwise.
/// @returns The number of received bytes on success, 0 if the socket is closed,
/// or -1 in case of an error.
/// @relates stream_socket
/// @post either the result is a `sec` or a positive (non-zero) integer
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
read
(
stream_socket
x
,
span
<
byte
>
buf
);
/// @post Either the functions returned a non-negative integer or the caller can
/// retrieve the error code by calling `last_socket_error()`.
ptrdiff_t
CAF_NET_EXPORT
read
(
stream_socket
x
,
span
<
byte
>
buf
);
///
Transmits data from `x` to its peer
.
/// @param x
C
onnected endpoint.
///
Sends data to `x`
.
/// @param x
A c
onnected endpoint.
/// @param buf Points to the message to send.
/// @returns The number of written bytes on success, otherwise an error code.
/// @returns The number of received bytes on success, 0 if the socket is closed,
/// or -1 in case of an error.
/// @relates stream_socket
/// @post either the result is a `sec` or a positive (non-zero) integer
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
write
(
stream_socket
x
,
span
<
const
byte
>
buf
);
ptrdiff_t
CAF_NET_EXPORT
write
(
stream_socket
x
,
span
<
const
byte
>
buf
);
/// Transmits data from `x` to its peer.
/// @param x
C
onnected endpoint.
/// @param x
A c
onnected endpoint.
/// @param bufs Points to the message to send, scattered across up to 10
/// buffers.
/// @returns The number of written bytes on success, otherwise an error code.
/// @relates stream_socket
/// @post either the result is a `sec` or a positive (non-zero) integer
/// @pre `bufs.size() < 10`
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
write
(
stream_socket
x
,
std
::
initializer_list
<
span
<
const
byte
>>
bufs
);
/// Converts the result from I/O operation on a ::stream_socket to either an
/// error code or a non-zero positive integer.
/// @relates stream_socket
variant
<
size_t
,
sec
>
CAF_NET_EXPORT
check_stream_socket_io_res
(
std
::
make_signed
<
size_t
>::
type
res
);
ptrdiff_t
CAF_NET_EXPORT
write
(
stream_socket
x
,
std
::
initializer_list
<
span
<
const
byte
>>
bufs
);
}
// namespace caf::net
libcaf_net/caf/net/stream_transport.hpp
View file @
ce5a53ca
...
...
@@ -74,16 +74,16 @@ public:
bool
handle_read_event
(
endpoint_manager
&
)
override
{
CAF_LOG_TRACE
(
CAF_ARG2
(
"handle"
,
this
->
handle
().
id
));
for
(
size_t
reads
=
0
;
reads
<
this
->
max_consecutive_reads_
;
++
reads
)
{
auto
buf
=
this
->
read_buf_
.
data
()
+
this
->
collected_
;
size_t
len
=
this
->
read_threshold_
-
this
->
collected_
;
auto
buf
=
this
->
read_buf_
.
data
()
+
collected_
;
size_t
len
=
read_threshold_
-
collected_
;
CAF_LOG_DEBUG
(
CAF_ARG2
(
"missing"
,
len
));
auto
ret
=
read
(
this
->
handle_
,
make_span
(
buf
,
len
));
auto
num_bytes
=
read
(
this
->
handle_
,
make_span
(
buf
,
len
));
CAF_LOG_DEBUG
(
CAF_ARG
(
len
)
<<
CAF_ARG2
(
"handle"
,
this
->
handle
().
id
)
<<
CAF_ARG
(
num_bytes
));
// Update state.
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
ret
))
{
CAF_LOG_DEBUG
(
CAF_ARG
(
len
)
<<
CAF_ARG
(
this
->
handle_
.
id
)
<<
CAF_ARG
(
*
num_bytes
));
this
->
collected_
+=
*
num_bytes
;
if
(
this
->
collected_
>=
this
->
read_threshold_
)
{
if
(
num_bytes
>
0
)
{
collected_
+=
num_bytes
;
if
(
collected_
>=
read_threshold_
)
{
if
(
auto
err
=
this
->
next_layer_
.
handle_data
(
*
this
,
make_span
(
this
->
read_buf_
)))
{
CAF_LOG_ERROR
(
"handle_data failed: "
<<
CAF_ARG
(
err
));
...
...
@@ -91,15 +91,16 @@ public:
}
this
->
prepare_next_read
();
}
}
else
{
auto
err
=
get
<
sec
>
(
ret
);
if
(
err
==
sec
::
unavailable_or_would_block
)
{
break
;
}
else
{
CAF_LOG_DEBUG
(
"read failed"
<<
CAF_ARG
(
err
));
this
->
next_layer_
.
handle_error
(
err
);
return
false
;
}
}
else
if
(
num_bytes
==
0
)
{
auto
err
=
sec
::
socket_disconnected
;
CAF_LOG_DEBUG
(
"read failed"
<<
CAF_ARG
(
err
));
this
->
next_layer_
.
handle_error
(
err
);
return
false
;
}
else
if
(
!
last_socket_error_is_temporary
())
{
auto
err
=
sec
::
socket_operation_failed
;
CAF_LOG_DEBUG
(
"read failed"
<<
CAF_ARG
(
err
));
this
->
next_layer_
.
handle_error
(
err
);
return
false
;
}
}
return
true
;
...
...
@@ -131,20 +132,23 @@ public:
CAF_ASSERT
(
!
buf
.
empty
());
auto
data
=
buf
.
data
()
+
written_
;
auto
len
=
buf
.
size
()
-
written_
;
auto
write_ret
=
write
(
this
->
handle
(),
make_span
(
data
,
len
));
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
write_ret
)
)
{
CAF_LOG_DEBUG
(
CAF_ARG
(
this
->
handle_
.
id
)
<<
CAF_ARG
(
*
num_bytes
));
written_
+=
*
num_bytes
;
if
(
written_
>=
buf
.
size
(
))
{
auto
num_bytes
=
write
(
this
->
handle
(),
make_span
(
data
,
len
));
if
(
num_bytes
>
0
)
{
CAF_LOG_DEBUG
(
CAF_ARG
(
this
->
handle_
.
id
)
<<
CAF_ARG
(
num_bytes
));
written_
+=
num_bytes
;
if
(
written_
>=
static_cast
<
ptrdiff_t
>
(
buf
.
size
()
))
{
recycle
();
written_
=
0
;
}
}
else
{
auto
err
=
get
<
sec
>
(
write_ret
);
if
(
err
!=
sec
::
unavailable_or_would_block
)
{
CAF_LOG_DEBUG
(
"send failed"
<<
CAF_ARG
(
err
));
this
->
next_layer_
.
handle_error
(
err
);
}
}
else
if
(
num_bytes
==
0
)
{
auto
err
=
sec
::
socket_disconnected
;
CAF_LOG_DEBUG
(
"send failed"
<<
CAF_ARG
(
err
));
this
->
next_layer_
.
handle_error
(
err
);
return
err
;
}
else
if
(
!
last_socket_error_is_temporary
())
{
auto
err
=
sec
::
socket_operation_failed
;
CAF_LOG_DEBUG
(
"send failed"
<<
CAF_ARG
(
err
));
this
->
next_layer_
.
handle_error
(
err
);
return
err
;
}
}
...
...
@@ -212,9 +216,9 @@ private:
}
write_queue_type
write_queue_
;
size
_t
written_
;
size
_t
read_threshold_
;
size
_t
collected_
;
ptrdiff
_t
written_
;
ptrdiff
_t
read_threshold_
;
ptrdiff
_t
collected_
;
size_t
max_
;
receive_policy_flag
rd_flag_
;
};
...
...
libcaf_net/src/multiplexer.cpp
View file @
ce5a53ca
...
...
@@ -155,15 +155,40 @@ bool multiplexer::poll_once(bool blocking) {
return
false
;
// We'll call poll() until poll() succeeds or fails.
for
(;;)
{
int
presult
;
int
presult
=
#ifdef CAF_WINDOWS
presult
=
::
WSAPoll
(
pollset_
.
data
(),
static_cast
<
ULONG
>
(
pollset_
.
size
()),
blocking
?
-
1
:
0
);
::
WSAPoll
(
pollset_
.
data
(),
static_cast
<
ULONG
>
(
pollset_
.
size
()),
blocking
?
-
1
:
0
);
#else
presult
=
::
poll
(
pollset_
.
data
(),
static_cast
<
nfds_t
>
(
pollset_
.
size
()),
blocking
?
-
1
:
0
);
::
poll
(
pollset_
.
data
(),
static_cast
<
nfds_t
>
(
pollset_
.
size
()),
blocking
?
-
1
:
0
);
#endif
if
(
presult
<
0
)
{
if
(
presult
>
0
)
{
CAF_LOG_DEBUG
(
"poll() on"
<<
pollset_
.
size
()
<<
"sockets reported"
<<
presult
<<
"event(s)"
);
// Scan pollset for events.
CAF_LOG_DEBUG
(
"scan pollset for socket events"
);
for
(
size_t
i
=
0
;
i
<
pollset_
.
size
()
&&
presult
>
0
;)
{
auto
revents
=
pollset_
[
i
].
revents
;
if
(
revents
!=
0
)
{
auto
events
=
pollset_
[
i
].
events
;
auto
mgr
=
managers_
[
i
];
auto
new_events
=
handle
(
mgr
,
events
,
revents
);
--
presult
;
if
(
new_events
==
0
)
{
del
(
i
);
continue
;
}
else
if
(
new_events
!=
events
)
{
pollset_
[
i
].
events
=
new_events
;
}
}
++
i
;
}
return
true
;
}
else
if
(
presult
==
0
)
{
// No activity.
return
false
;
}
else
{
auto
code
=
last_socket_error
();
switch
(
code
)
{
case
std
:
:
errc
::
interrupted
:
{
...
...
@@ -186,33 +211,7 @@ bool multiplexer::poll_once(bool blocking) {
CAF_CRITICAL
(
msg
.
c_str
());
}
}
// Rinse and repeat.
continue
;
}
CAF_LOG_DEBUG
(
"poll() on"
<<
pollset_
.
size
()
<<
"sockets reported"
<<
presult
<<
"event(s)"
);
// No activity.
if
(
presult
==
0
)
return
false
;
// Scan pollset for events.
CAF_LOG_DEBUG
(
"scan pollset for socket events"
);
for
(
size_t
i
=
0
;
i
<
pollset_
.
size
()
&&
presult
>
0
;)
{
auto
revents
=
pollset_
[
i
].
revents
;
if
(
revents
!=
0
)
{
auto
events
=
pollset_
[
i
].
events
;
auto
mgr
=
managers_
[
i
];
auto
new_events
=
handle
(
mgr
,
events
,
revents
);
--
presult
;
if
(
new_events
==
0
)
{
del
(
i
);
continue
;
}
else
if
(
new_events
!=
events
)
{
pollset_
[
i
].
events
=
new_events
;
}
}
++
i
;
}
return
true
;
}
}
...
...
@@ -302,15 +301,13 @@ void multiplexer::write_to_pipe(uint8_t opcode, const socket_manager_ptr& mgr) {
buf
[
0
]
=
static_cast
<
byte
>
(
opcode
);
auto
value
=
reinterpret_cast
<
intptr_t
>
(
mgr
.
get
());
memcpy
(
buf
.
data
()
+
1
,
&
value
,
sizeof
(
intptr_t
));
variant
<
size_t
,
sec
>
res
;
ptrdiff_t
res
=
-
1
;
{
// Lifetime scope of guard.
std
::
lock_guard
<
std
::
mutex
>
guard
{
write_lock_
};
if
(
write_handle_
!=
invalid_socket
)
res
=
write
(
write_handle_
,
buf
);
else
res
=
sec
::
socket_invalid
;
}
if
(
holds_alternative
<
sec
>
(
res
)
&&
opcode
!=
4
)
if
(
res
<=
0
&&
opcode
!=
4
)
mgr
->
deref
();
}
...
...
libcaf_net/src/pipe_socket.cpp
View file @
ce5a53ca
...
...
@@ -49,12 +49,12 @@ expected<std::pair<pipe_socket, pipe_socket>> make_pipe() {
}
}
variant
<
size_t
,
sec
>
write
(
pipe_socket
x
,
span
<
const
byte
>
buf
)
{
ptrdiff_t
write
(
pipe_socket
x
,
span
<
const
byte
>
buf
)
{
// On Windows, a pipe consists of two stream sockets.
return
write
(
socket_cast
<
stream_socket
>
(
x
),
buf
);
}
variant
<
size_t
,
sec
>
read
(
pipe_socket
x
,
span
<
byte
>
buf
)
{
ptrdiff_t
read
(
pipe_socket
x
,
span
<
byte
>
buf
)
{
// On Windows, a pipe consists of two stream sockets.
return
read
(
socket_cast
<
stream_socket
>
(
x
),
buf
);
}
...
...
@@ -80,23 +80,16 @@ expected<std::pair<pipe_socket, pipe_socket>> make_pipe() {
return
std
::
make_pair
(
pipe_socket
{
pipefds
[
0
]},
pipe_socket
{
pipefds
[
1
]});
}
variant
<
size_t
,
sec
>
write
(
pipe_socket
x
,
span
<
const
byte
>
buf
)
{
auto
res
=
::
write
(
x
.
id
,
reinterpret_cast
<
socket_send_ptr
>
(
buf
.
data
()),
buf
.
size
());
return
check_pipe_socket_io_res
(
res
);
ptrdiff_t
write
(
pipe_socket
x
,
span
<
const
byte
>
buf
)
{
return
::
write
(
x
.
id
,
reinterpret_cast
<
socket_send_ptr
>
(
buf
.
data
()),
buf
.
size
());
}
variant
<
size_t
,
sec
>
read
(
pipe_socket
x
,
span
<
byte
>
buf
)
{
auto
res
=
::
read
(
x
.
id
,
reinterpret_cast
<
socket_recv_ptr
>
(
buf
.
data
()),
buf
.
size
());
return
check_pipe_socket_io_res
(
res
);
ptrdiff_t
read
(
pipe_socket
x
,
span
<
byte
>
buf
)
{
return
::
read
(
x
.
id
,
reinterpret_cast
<
socket_recv_ptr
>
(
buf
.
data
()),
buf
.
size
());
}
#endif // CAF_WINDOWS
variant
<
size_t
,
sec
>
check_pipe_socket_io_res
(
std
::
make_signed
<
size_t
>::
type
res
)
{
return
check_stream_socket_io_res
(
res
);
}
}
// namespace caf::net
libcaf_net/src/pollset_updater.cpp
View file @
ce5a53ca
...
...
@@ -42,10 +42,10 @@ pollset_updater::~pollset_updater() {
bool
pollset_updater
::
handle_read_event
()
{
for
(;;)
{
auto
r
es
=
read
(
handle
(),
make_span
(
buf_
.
data
()
+
buf_size_
,
buf_
.
size
()
-
buf_size_
));
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
res
)
)
{
buf_size_
+=
*
num_bytes
;
auto
num_byt
es
=
read
(
handle
(),
make_span
(
buf_
.
data
()
+
buf_size_
,
buf_
.
size
()
-
buf_size_
));
if
(
num_bytes
>
0
)
{
buf_size_
+=
static_cast
<
size_t
>
(
num_bytes
)
;
if
(
buf_
.
size
()
==
buf_size_
)
{
buf_size_
=
0
;
auto
opcode
=
static_cast
<
uint8_t
>
(
buf_
[
0
]);
...
...
@@ -70,7 +70,7 @@ bool pollset_updater::handle_read_event() {
}
}
}
else
{
return
get
<
sec
>
(
res
)
==
sec
::
unavailable_or_would_block
;
return
num_bytes
<
0
&&
last_socket_error_is_temporary
()
;
}
}
}
...
...
libcaf_net/src/socket.cpp
View file @
ce5a53ca
...
...
@@ -103,6 +103,11 @@ std::errc last_socket_error() {
abort
();
}
bool
last_socket_error_is_temporary
()
{
int
wsa_code
=
WSAGetLastError
();
return
wsa_code
==
WSAEWOULDBLOCK
||
wsa_code
==
WSATRY_AGAIN
;
}
std
::
string
last_socket_error_as_string
()
{
int
wsa_code
=
WSAGetLastError
();
LPTSTR
errorText
=
NULL
;
...
...
@@ -149,6 +154,15 @@ std::errc last_socket_error() {
return
static_cast
<
std
::
errc
>
(
errno
);
}
bool
last_socket_error_is_temporary
()
{
auto
code
=
errno
;
# if EAGAIN == EWOULDBLOCK
return
code
==
EAGAIN
;
# else
return
code
==
EAGAIN
||
code
==
EWOULDBLOCK
;
# endif
}
std
::
string
last_socket_error_as_string
()
{
return
strerror
(
errno
);
}
...
...
libcaf_net/src/stream_socket.cpp
View file @
ce5a53ca
...
...
@@ -168,22 +168,19 @@ error nodelay(stream_socket x, bool new_value) {
return
none
;
}
variant
<
size_t
,
sec
>
read
(
stream_socket
x
,
span
<
byte
>
buf
)
{
auto
res
=
::
recv
(
x
.
id
,
reinterpret_cast
<
socket_recv_ptr
>
(
buf
.
data
()),
buf
.
size
(),
no_sigpipe_io_flag
);
return
check_stream_socket_io_res
(
res
);
ptrdiff_t
read
(
stream_socket
x
,
span
<
byte
>
buf
)
{
return
::
recv
(
x
.
id
,
reinterpret_cast
<
socket_recv_ptr
>
(
buf
.
data
()),
buf
.
size
(),
no_sigpipe_io_flag
);
}
variant
<
size_t
,
sec
>
write
(
stream_socket
x
,
span
<
const
byte
>
buf
)
{
auto
res
=
::
send
(
x
.
id
,
reinterpret_cast
<
socket_send_ptr
>
(
buf
.
data
()),
buf
.
size
(),
no_sigpipe_io_flag
);
return
check_stream_socket_io_res
(
res
);
ptrdiff_t
write
(
stream_socket
x
,
span
<
const
byte
>
buf
)
{
return
::
send
(
x
.
id
,
reinterpret_cast
<
socket_send_ptr
>
(
buf
.
data
()),
buf
.
size
(),
no_sigpipe_io_flag
);
}
#ifdef CAF_WINDOWS
variant
<
size_t
,
sec
>
write
(
stream_socket
x
,
std
::
initializer_list
<
span
<
const
byte
>>
bufs
)
{
ptrdiff_t
write
(
stream_socket
x
,
std
::
initializer_list
<
span
<
const
byte
>>
bufs
)
{
CAF_ASSERT
(
bufs
.
size
()
<
10
);
WSABUF
buf_array
[
10
];
auto
convert
=
[](
span
<
const
byte
>
buf
)
{
...
...
@@ -195,44 +192,21 @@ variant<size_t, sec> write(stream_socket x,
DWORD
bytes_sent
=
0
;
auto
res
=
WSASend
(
x
.
id
,
buf_array
,
static_cast
<
DWORD
>
(
bufs
.
size
()),
&
bytes_sent
,
0
,
nullptr
,
nullptr
);
if
(
res
!=
0
)
{
auto
code
=
last_socket_error
();
if
(
code
==
std
::
errc
::
operation_would_block
||
code
==
std
::
errc
::
resource_unavailable_try_again
)
return
sec
::
unavailable_or_would_block
;
return
sec
::
socket_operation_failed
;
}
return
static_cast
<
size_t
>
(
bytes_sent
);
return
(
res
==
0
)
?
bytes_sent
:
-
1
;
}
#else // CAF_WINDOWS
variant
<
size_t
,
sec
>
write
(
stream_socket
x
,
std
::
initializer_list
<
span
<
const
byte
>>
bufs
)
{
ptrdiff_t
write
(
stream_socket
x
,
std
::
initializer_list
<
span
<
const
byte
>>
bufs
)
{
CAF_ASSERT
(
bufs
.
size
()
<
10
);
iovec
buf_array
[
10
];
auto
convert
=
[](
span
<
const
byte
>
buf
)
{
return
iovec
{
const_cast
<
byte
*>
(
buf
.
data
()),
buf
.
size
()};
};
std
::
transform
(
bufs
.
begin
(),
bufs
.
end
(),
std
::
begin
(
buf_array
),
convert
);
auto
res
=
writev
(
x
.
id
,
buf_array
,
static_cast
<
int
>
(
bufs
.
size
()));
return
check_stream_socket_io_res
(
res
);
return
writev
(
x
.
id
,
buf_array
,
static_cast
<
int
>
(
bufs
.
size
()));
}
#endif // CAF_WINDOWS
variant
<
size_t
,
sec
>
check_stream_socket_io_res
(
std
::
make_signed
<
size_t
>::
type
res
)
{
if
(
res
==
0
)
return
sec
::
socket_disconnected
;
if
(
res
<
0
)
{
auto
code
=
last_socket_error
();
if
(
code
==
std
::
errc
::
operation_would_block
||
code
==
std
::
errc
::
resource_unavailable_try_again
)
return
sec
::
unavailable_or_would_block
;
return
sec
::
socket_operation_failed
;
}
return
static_cast
<
size_t
>
(
res
);
}
}
// namespace caf::net
libcaf_net/test/endpoint_manager.cpp
View file @
ce5a53ca
...
...
@@ -90,13 +90,13 @@ public:
template
<
class
Manager
>
bool
handle_read_event
(
Manager
&
)
{
auto
r
es
=
read
(
handle_
,
read_buf_
);
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
res
)
)
{
auto
num_byt
es
=
read
(
handle_
,
read_buf_
);
if
(
num_bytes
>
0
)
{
data_
->
insert
(
data_
->
end
(),
read_buf_
.
begin
(),
read_buf_
.
begin
()
+
*
num_bytes
);
read_buf_
.
begin
()
+
num_bytes
);
return
true
;
}
return
get
<
sec
>
(
res
)
==
sec
::
unavailable_or_would_block
;
return
num_bytes
<
0
&&
last_socket_error_is_temporary
()
;
}
template
<
class
Manager
>
...
...
@@ -106,12 +106,12 @@ public:
if
(
auto
err
=
sink
(
x
->
msg
->
payload
))
CAF_FAIL
(
"serializing failed: "
<<
err
);
}
auto
r
es
=
write
(
handle_
,
buf_
);
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
res
)
)
{
buf_
.
erase
(
buf_
.
begin
(),
buf_
.
begin
()
+
*
num_bytes
);
auto
num_byt
es
=
write
(
handle_
,
buf_
);
if
(
num_bytes
>
0
)
{
buf_
.
erase
(
buf_
.
begin
(),
buf_
.
begin
()
+
num_bytes
);
return
buf_
.
size
()
>
0
;
}
return
get
<
sec
>
(
res
)
==
sec
::
unavailable_or_would_block
;
return
num_bytes
<
0
&&
last_socket_error_is_temporary
()
;
}
void
handle_error
(
sec
)
{
...
...
@@ -164,8 +164,8 @@ CAF_TEST(send and receive) {
auto
buf
=
std
::
make_shared
<
byte_buffer
>
();
auto
sockets
=
unbox
(
make_stream_socket_pair
());
CAF_CHECK_EQUAL
(
nonblocking
(
sockets
.
second
,
true
),
none
);
CAF_CHECK_EQUAL
(
read
(
sockets
.
second
,
read_buf
),
sec
::
unavailable_or_would_block
);
CAF_CHECK_EQUAL
(
read
(
sockets
.
second
,
read_buf
),
-
1
);
CAF_CHECK
(
last_socket_error_is_temporary
()
);
auto
guard
=
detail
::
make_scope_guard
([
&
]
{
close
(
sockets
.
second
);
});
auto
mgr
=
make_endpoint_manager
(
mpx
,
sys
,
dummy_transport
{
sockets
.
first
,
buf
});
...
...
@@ -208,11 +208,14 @@ CAF_TEST(resolve and proxy communication) {
[
&
]
{
CAF_FAIL
(
"manager did not respond with a proxy."
);
});
run
();
auto
read_res
=
read
(
sockets
.
second
,
read_buf
);
if
(
!
holds_alternative
<
size_t
>
(
read_res
))
{
CAF_ERROR
(
"read() returned an error: "
<<
get
<
sec
>
(
read_res
));
if
(
read_res
<=
0
)
{
std
::
string
msg
=
"socket closed"
;
if
(
read_res
<
0
)
msg
=
last_socket_error_as_string
();
CAF_ERROR
(
"read() failed: "
<<
msg
);
return
;
}
read_buf
.
resize
(
ge
t
<
size_t
>
(
read_res
));
read_buf
.
resize
(
static_cas
t
<
size_t
>
(
read_res
));
CAF_MESSAGE
(
"receive buffer contains "
<<
read_buf
.
size
()
<<
" bytes"
);
message
msg
;
binary_deserializer
source
{
sys
,
read_buf
};
...
...
libcaf_net/test/multiplexer.cpp
View file @
ce5a53ca
...
...
@@ -59,26 +59,25 @@ public:
bool
handle_read_event
()
override
{
if
(
read_capacity
()
<
1024
)
rd_buf_
.
resize
(
rd_buf_
.
size
()
+
2048
);
auto
r
es
=
read
(
handle
(),
make_span
(
read_position_begin
(),
read_capacity
()));
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
res
)
)
{
CAF_ASSERT
(
*
num_bytes
>
0
);
rd_buf_pos_
+=
*
num_bytes
;
auto
num_byt
es
=
read
(
handle
(),
make_span
(
read_position_begin
(),
read_capacity
()));
if
(
num_bytes
>
0
)
{
CAF_ASSERT
(
num_bytes
>
0
);
rd_buf_pos_
+=
num_bytes
;
return
true
;
}
return
get
<
sec
>
(
res
)
==
sec
::
unavailable_or_would_block
;
return
num_bytes
<
0
&&
last_socket_error_is_temporary
()
;
}
bool
handle_write_event
()
override
{
if
(
wr_buf_
.
size
()
==
0
)
return
false
;
auto
res
=
write
(
handle
(),
wr_buf_
);
if
(
auto
num_bytes
=
get_if
<
size_t
>
(
&
res
))
{
CAF_ASSERT
(
*
num_bytes
>
0
);
wr_buf_
.
erase
(
wr_buf_
.
begin
(),
wr_buf_
.
begin
()
+
*
num_bytes
);
auto
num_bytes
=
write
(
handle
(),
wr_buf_
);
if
(
num_bytes
>
0
)
{
wr_buf_
.
erase
(
wr_buf_
.
begin
(),
wr_buf_
.
begin
()
+
num_bytes
);
return
wr_buf_
.
size
()
>
0
;
}
return
get
<
sec
>
(
res
)
==
sec
::
unavailable_or_would_block
;
return
num_bytes
<
0
&&
last_socket_error_is_temporary
()
;
}
void
handle_error
(
sec
code
)
override
{
...
...
libcaf_net/test/stream_application.cpp
View file @
ce5a53ca
...
...
@@ -48,12 +48,6 @@ namespace {
using
transport_type
=
stream_transport
<
basp
::
application
>
;
size_t
fetch_size
(
variant
<
size_t
,
sec
>
x
)
{
if
(
holds_alternative
<
sec
>
(
x
))
CAF_FAIL
(
"read/write failed: "
<<
to_string
(
get
<
sec
>
(
x
)));
return
get
<
size_t
>
(
x
);
}
struct
config
:
actor_system_config
{
config
()
{
put
(
content
,
"caf.middleman.this-node"
,
unbox
(
make_uri
(
"test:earth"
)));
...
...
@@ -88,7 +82,7 @@ struct fixture : host_fixture, test_coordinator_fixture<config> {
template
<
class
...
Ts
>
void
mock
(
const
Ts
&
...
xs
)
{
auto
buf
=
to_buf
(
xs
...);
if
(
fetch_size
(
write
(
sock
,
buf
))
!=
buf
.
size
(
))
if
(
write
(
sock
,
buf
)
!=
static_cast
<
ptrdiff_t
>
(
buf
.
size
()
))
CAF_FAIL
(
"unable to write "
<<
buf
.
size
()
<<
" bytes"
);
run
();
}
...
...
@@ -107,14 +101,14 @@ struct fixture : host_fixture, test_coordinator_fixture<config> {
void
consume_handshake
()
{
byte_buffer
buf
(
basp
::
header_size
);
if
(
fetch_size
(
read
(
sock
,
buf
)
)
!=
basp
::
header_size
)
if
(
read
(
sock
,
buf
)
!=
basp
::
header_size
)
CAF_FAIL
(
"unable to read "
<<
basp
::
header_size
<<
" bytes"
);
auto
hdr
=
basp
::
header
::
from_bytes
(
buf
);
if
(
hdr
.
type
!=
basp
::
message_type
::
handshake
||
hdr
.
payload_len
==
0
||
hdr
.
operation_data
!=
basp
::
version
)
CAF_FAIL
(
"invalid handshake header"
);
buf
.
resize
(
hdr
.
payload_len
);
if
(
fetch_size
(
read
(
sock
,
buf
))
!=
hdr
.
payload_len
)
if
(
read
(
sock
,
buf
)
!=
static_cast
<
ptrdiff_t
>
(
hdr
.
payload_len
)
)
CAF_FAIL
(
"unable to read "
<<
hdr
.
payload_len
<<
" bytes"
);
node_id
nid
;
std
::
vector
<
std
::
string
>
app_ids
;
...
...
@@ -158,7 +152,7 @@ struct fixture : host_fixture, test_coordinator_fixture<config> {
do { \
CAF_MESSAGE("receive " << msg_type); \
byte_buffer buf(basp::header_size); \
if (
fetch_size(read(sock, buf)) != basp::header_size)
\
if (
read(sock, buf) != static_cast<ptrdiff_t>(basp::header_size))
\
CAF_FAIL("unable to read " << basp::header_size << " bytes"); \
auto hdr = basp::header::from_bytes(buf); \
CAF_CHECK_EQUAL(hdr.type, msg_type); \
...
...
@@ -166,7 +160,7 @@ struct fixture : host_fixture, test_coordinator_fixture<config> {
if (!std::is_same<decltype(std::make_tuple(__VA_ARGS__)), \
std::tuple<unit_t>>::value) { \
buf.resize(hdr.payload_len); \
if (
fetch_size(read(sock, buf)) != size_t{hdr.payload_len})
\
if (
read(sock, buf) != static_cast<ptrdiff_t>(hdr.payload_len))
\
CAF_FAIL("unable to read " << hdr.payload_len << " bytes"); \
binary_deserializer source{sys, buf}; \
if (auto err = source(__VA_ARGS__)) \
...
...
libcaf_net/test/stream_socket.cpp
View file @
ce5a53ca
...
...
@@ -75,8 +75,10 @@ struct fixture : host_fixture {
CAF_TEST_FIXTURE_SCOPE
(
network_socket_tests
,
fixture
)
CAF_TEST
(
read
on
empty
sockets
)
{
CAF_CHECK_EQUAL
(
read
(
first
,
rd_buf
),
sec
::
unavailable_or_would_block
);
CAF_CHECK_EQUAL
(
read
(
second
,
rd_buf
),
sec
::
unavailable_or_would_block
);
CAF_CHECK_EQUAL
(
read
(
first
,
rd_buf
),
-
1
);
CAF_CHECK
(
last_socket_error_is_temporary
());
CAF_CHECK_EQUAL
(
read
(
second
,
rd_buf
),
-
1
);
CAF_CHECK
(
last_socket_error_is_temporary
());
}
CAF_TEST
(
transfer
data
from
first
to
second
socket
)
{
...
...
@@ -97,7 +99,7 @@ CAF_TEST(transfer data from second to first socket) {
CAF_TEST
(
shut
down
first
socket
and
observe
shutdown
on
the
second
one
)
{
close
(
first
);
CAF_CHECK_EQUAL
(
read
(
second
,
rd_buf
),
sec
::
socket_disconnected
);
CAF_CHECK_EQUAL
(
read
(
second
,
rd_buf
),
0
);
first
.
id
=
invalid_socket_id
;
}
...
...
libcaf_net/test/stream_transport.cpp
View file @
ce5a53ca
...
...
@@ -184,9 +184,11 @@ CAF_TEST(resolve and proxy communication) {
[
&
]
{
CAF_FAIL
(
"manager did not respond with a proxy."
);
});
run
();
auto
read_res
=
read
(
recv_socket_guard
.
socket
(),
recv_buf
);
if
(
!
holds_alternative
<
size_t
>
(
read_res
))
CAF_FAIL
(
"read() returned an error: "
<<
get
<
sec
>
(
read_res
));
recv_buf
.
resize
(
get
<
size_t
>
(
read_res
));
if
(
read_res
<
0
)
CAF_FAIL
(
"read() returned an error: "
<<
last_socket_error_as_string
);
else
if
(
read_res
==
0
)
CAF_FAIL
(
"read() returned 0 (socket closed)"
);
recv_buf
.
resize
(
static_cast
<
size_t
>
(
read_res
));
CAF_MESSAGE
(
"receive buffer contains "
<<
recv_buf
.
size
()
<<
" bytes"
);
message
msg
;
binary_deserializer
source
{
sys
,
recv_buf
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment