Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
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
Operations
Operations
Metrics
Environments
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 Framework
Commits
28461e75
Unverified
Commit
28461e75
authored
May 18, 2023
by
Raphael
Committed by
GitHub
May 18, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1412
Fix initialization on Windows and enable Robot tests on Windows CI
parents
612e34fa
aa7f2efb
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
27 changed files
with
202 additions
and
68 deletions
+202
-68
.ci/run.sh
.ci/run.sh
+7
-0
.ci/windows/Dockerfile
.ci/windows/Dockerfile
+8
-2
.ci/windows/build.cmd
.ci/windows/build.cmd
+2
-2
CHANGELOG.md
CHANGELOG.md
+5
-0
examples/flow/iota.cpp
examples/flow/iota.cpp
+1
-1
examples/flow/observe-on.cpp
examples/flow/observe-on.cpp
+1
-1
examples/flow/spsc-buffer-resource.cpp
examples/flow/spsc-buffer-resource.cpp
+1
-1
examples/http/time-server.cpp
examples/http/time-server.cpp
+2
-1
examples/length_prefix_framing/chat-client.cpp
examples/length_prefix_framing/chat-client.cpp
+7
-5
examples/length_prefix_framing/chat-server.cpp
examples/length_prefix_framing/chat-server.cpp
+8
-5
examples/message_passing/fan_out_request.cpp
examples/message_passing/fan_out_request.cpp
+3
-3
examples/remoting/remote_spawn.cpp
examples/remoting/remote_spawn.cpp
+1
-1
examples/web_socket/echo.cpp
examples/web_socket/echo.cpp
+5
-5
examples/web_socket/hello-client.cpp
examples/web_socket/hello-client.cpp
+5
-5
examples/web_socket/stock-ticker.cpp
examples/web_socket/stock-ticker.cpp
+5
-4
libcaf_core/caf/actor_system.hpp
libcaf_core/caf/actor_system.hpp
+33
-0
libcaf_core/caf/detail/type_traits.hpp
libcaf_core/caf/detail/type_traits.hpp
+17
-0
libcaf_core/caf/exec_main.hpp
libcaf_core/caf/exec_main.hpp
+20
-0
libcaf_core/caf/uri.hpp
libcaf_core/caf/uri.hpp
+1
-1
libcaf_io/src/io/network/default_multiplexer.cpp
libcaf_io/src/io/network/default_multiplexer.cpp
+9
-4
libcaf_net/caf/net/middleman.hpp
libcaf_net/caf/net/middleman.hpp
+12
-0
libcaf_net/caf/net/web_socket/upper_layer.hpp
libcaf_net/caf/net/web_socket/upper_layer.hpp
+1
-1
libcaf_net/src/net/middleman.cpp
libcaf_net/src/net/middleman.cpp
+11
-0
manual/net/Overview.rst
manual/net/Overview.rst
+20
-0
robot/http/rest.robot
robot/http/rest.robot
+3
-6
robot/web_socket/echo.robot
robot/web_socket/echo.robot
+7
-10
robot/web_socket/quote-server.robot
robot/web_socket/quote-server.robot
+7
-10
No files found.
.ci/run.sh
View file @
28461e75
...
@@ -77,6 +77,13 @@ else
...
@@ -77,6 +77,13 @@ else
exit
1
exit
1
fi
fi
# Pick up Cirrus environment variables.
if
[
-z
"
$CAF_NUM_CORES
"
]
;
then
if
[
!
-z
"
$CIRRUS_CPU
"
]
;
then
CAF_NUM_CORES
=
$CIRRUS_CPU
fi
fi
runBuild
()
{
runBuild
()
{
cat
"
$InitFile
"
cat
"
$InitFile
"
cd
"
$BuildDir
"
cd
"
$BuildDir
"
...
...
.ci/windows/Dockerfile
View file @
28461e75
...
@@ -13,8 +13,14 @@ RUN Set-ExecutionPolicy Bypass -Scope Process -Force; \
...
@@ -13,8 +13,14 @@ RUN Set-ExecutionPolicy Bypass -Scope Process -Force; \
RUN
choco
install
-y
--no-progress
visualstudio2022buildtools
RUN
choco
install
-y
--no-progress
visualstudio2022buildtools
RUN
choco
install
-y
--no-progress
visualstudio2022-workload-vctools
RUN
choco
install
-y
--no-progress
visualstudio2022-workload-vctools
# Install Git and OpenSSL.
# Install Git, OpenSSL and Python.
RUN
choco
install
-y
--no-progress
msysgit openssl
RUN
choco
install
-y
--no-progress
msysgit openssl python
# Install Robot Framework and dependencies.
RUN
python.exe
-m
pip
install
\
robotframework
\
robotframework-requests
\
robotframework-websocketclient
# Add git to the global PATH
# Add git to the global PATH
SHELL
[ "cmd", "/c" ]
SHELL
[ "cmd", "/c" ]
...
...
.ci/windows/build.cmd
View file @
28461e75
...
@@ -5,10 +5,10 @@ cmake.exe ^
...
@@ -5,10 +5,10 @@ cmake.exe ^
-B
build
^
-B
build
^
-G
"Visual Studio 17 2022"
^
-G
"Visual Studio 17 2022"
^
-C
".ci\debug-flags.cmake"
^
-C
".ci\debug-flags.cmake"
^
-D
EXTRA
_FLAGS
=
/MP
%CIRRUS_CPU%
^
-D
CAF
_ENABLE_ROBOT_TESTS
=
ON
^
-DBUILD
_SHARED_LIBS
=
OFF
^
-DBUILD
_SHARED_LIBS
=
OFF
^
-DCMAKE
_C_COMPILER
=
cl
.exe
^
-DCMAKE
_C_COMPILER
=
cl
.exe
^
-DCMAKE
_CXX_COMPILER
=
cl
.exe
^
-DCMAKE
_CXX_COMPILER
=
cl
.exe
^
-DOPENSSL
_ROOT_DIR
=
"C:\Program Files\OpenSSL-Win64"
-DOPENSSL
_ROOT_DIR
=
"C:\Program Files\OpenSSL-Win64"
cmake
.exe
-
-build
build
-
-target
install
-
-config
debug
||
exit
\b
1
cmake
.exe
-
-build
build
-
-
parallel
%CIRRUS_CPU%
-
-
target
install
-
-config
debug
||
exit
\b
1
CHANGELOG.md
View file @
28461e75
...
@@ -17,6 +17,11 @@ is based on [Keep a Changelog](https://keepachangelog.com).
...
@@ -17,6 +17,11 @@ is based on [Keep a Changelog](https://keepachangelog.com).
versions of OpenSSL). Please note that these lists are
*not*
recommended as
versions of OpenSSL). Please note that these lists are
*not*
recommended as
safe defaults, which is why we are no longer setting these values.
safe defaults, which is why we are no longer setting these values.
### Fixed
-
Add missing initialization code for the new caf-net module when using the
`CAF_MAIN`
macro. This fixes the
`WSANOTINITIALISED`
error on Windows (#1409).
## [0.19.1] - 2023-05-01
## [0.19.1] - 2023-05-01
### Added
### Added
...
...
examples/flow/iota.cpp
View file @
28461e75
...
@@ -29,7 +29,7 @@ void caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -29,7 +29,7 @@ void caf_main(caf::actor_system& sys, const config& cfg) {
// Only take the requested number of items from the infinite sequence.
// Only take the requested number of items from the infinite sequence.
.
take
(
n
)
.
take
(
n
)
// Print each integer.
// Print each integer.
.
for_each
([](
int
x
)
{
std
::
cout
<<
x
<<
'\n'
;
});
.
for_each
([](
int
x
)
{
std
::
cout
<<
x
<<
std
::
endl
;
});
});
});
}
}
// --(rst-main-end)--
// --(rst-main-end)--
...
...
examples/flow/observe-on.cpp
View file @
28461e75
...
@@ -35,7 +35,7 @@ void caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -35,7 +35,7 @@ void caf_main(caf::actor_system& sys, const config& cfg) {
// Switch to `snk` for further processing.
// Switch to `snk` for further processing.
.
observe_on
(
snk
)
.
observe_on
(
snk
)
// Print each integer.
// Print each integer.
.
for_each
([](
int
x
)
{
std
::
cout
<<
x
<<
'\n'
;
});
.
for_each
([](
int
x
)
{
std
::
cout
<<
x
<<
std
::
endl
;
});
// Allow the actors to run. After this point, we may no longer dereference
// Allow the actors to run. After this point, we may no longer dereference
// the `src` and `snk` pointers! Calling these manually is optional. When
// the `src` and `snk` pointers! Calling these manually is optional. When
// removing these two lines, CAF automatically launches the actors at scope
// removing these two lines, CAF automatically launches the actors at scope
...
...
examples/flow/spsc-buffer-resource.cpp
View file @
28461e75
...
@@ -37,7 +37,7 @@ void sink(caf::event_based_actor* self, caf::async::consumer_resource<int> in) {
...
@@ -37,7 +37,7 @@ void sink(caf::event_based_actor* self, caf::async::consumer_resource<int> in) {
// Lift the input to an observable flow.
// Lift the input to an observable flow.
.
from_resource
(
std
::
move
(
in
))
.
from_resource
(
std
::
move
(
in
))
// Print each integer.
// Print each integer.
.
for_each
([](
int
x
)
{
std
::
cout
<<
x
<<
'\n'
;
});
.
for_each
([](
int
x
)
{
std
::
cout
<<
x
<<
std
::
endl
;
});
}
}
// --(rst-sink-end)--
// --(rst-sink-end)--
...
...
examples/http/time-server.cpp
View file @
28461e75
...
@@ -77,7 +77,8 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -77,7 +77,8 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
}
}
// Note: the actor system will only wait for actors on default. Since we don't
// Note: the actor system will only wait for actors on default. Since we don't
// start actors, we need to block on something else.
// start actors, we need to block on something else.
std
::
cout
<<
"Server is up and running. Press <enter> to shut down.
\n
"
;
std
::
cout
<<
"Server is up and running. Press <enter> to shut down."
<<
std
::
endl
;
getchar
();
getchar
();
std
::
cout
<<
"Terminating.
\n
"
;
std
::
cout
<<
"Terminating.
\n
"
;
return
EXIT_SUCCESS
;
return
EXIT_SUCCESS
;
...
...
examples/length_prefix_framing/chat-client.cpp
View file @
28461e75
...
@@ -70,11 +70,13 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -70,11 +70,13 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
pull
pull
.
observe_on
(
self
)
//
.
observe_on
(
self
)
//
.
do_on_error
([](
const
caf
::
error
&
err
)
{
.
do_on_error
([](
const
caf
::
error
&
err
)
{
std
::
cout
<<
"*** connection error: "
<<
to_string
(
err
)
<<
'\n'
;
std
::
cout
<<
"*** connection error: "
<<
to_string
(
err
)
<<
std
::
endl
;
})
})
.
do_finally
([
self
]
{
.
do_finally
([
self
]
{
std
::
cout
<<
"*** lost connection to server -> quit
\n
"
std
::
cout
<<
"*** lost connection to server -> quit
\n
"
<<
"*** use CTRL+D or CTRL+C to terminate
\n
"
;
"*** use CTRL+D or CTRL+C to terminate"
<<
std
::
endl
;
self
->
quit
();
self
->
quit
();
})
})
.
for_each
([](
const
lp
::
frame
&
frame
)
{
.
for_each
([](
const
lp
::
frame
&
frame
)
{
...
@@ -83,10 +85,10 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -83,10 +85,10 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
auto
str
=
std
::
string_view
{
auto
str
=
std
::
string_view
{
reinterpret_cast
<
const
char
*>
(
bytes
.
data
()),
bytes
.
size
()};
reinterpret_cast
<
const
char
*>
(
bytes
.
data
()),
bytes
.
size
()};
if
(
std
::
all_of
(
str
.
begin
(),
str
.
end
(),
::
isprint
))
{
if
(
std
::
all_of
(
str
.
begin
(),
str
.
end
(),
::
isprint
))
{
std
::
cout
<<
str
<<
'\n'
;
std
::
cout
<<
str
<<
std
::
endl
;
}
else
{
}
else
{
std
::
cout
<<
"<non-ascii-data of size "
<<
bytes
.
size
()
std
::
cout
<<
"<non-ascii-data of size "
<<
bytes
.
size
()
<<
">"
<<
">
\n
"
;
<<
std
::
endl
;
}
}
});
});
});
});
...
...
examples/length_prefix_framing/chat-server.cpp
View file @
28461e75
...
@@ -49,7 +49,7 @@ void worker_impl(caf::event_based_actor* self,
...
@@ -49,7 +49,7 @@ void worker_impl(caf::event_based_actor* self,
messages
.
for_each
([](
const
message_t
&
msg
)
{
messages
.
for_each
([](
const
message_t
&
msg
)
{
const
auto
&
[
conn
,
frame
]
=
msg
;
const
auto
&
[
conn
,
frame
]
=
msg
;
std
::
cout
<<
"*** got message of size "
<<
frame
.
size
()
<<
" from "
std
::
cout
<<
"*** got message of size "
<<
frame
.
size
()
<<
" from "
<<
to_string
(
conn
)
<<
'\n'
;
<<
to_string
(
conn
)
<<
std
::
endl
;
});
});
// Connect the flows for each incoming connection.
// Connect the flows for each incoming connection.
events
events
...
@@ -58,7 +58,8 @@ void worker_impl(caf::event_based_actor* self,
...
@@ -58,7 +58,8 @@ void worker_impl(caf::event_based_actor* self,
[
self
,
messages
,
pub
=
std
::
move
(
pub
)](
const
auto
&
event
)
mutable
{
[
self
,
messages
,
pub
=
std
::
move
(
pub
)](
const
auto
&
event
)
mutable
{
// Each connection gets a unique ID.
// Each connection gets a unique ID.
auto
conn
=
caf
::
uuid
::
random
();
auto
conn
=
caf
::
uuid
::
random
();
std
::
cout
<<
"*** accepted new connection "
<<
to_string
(
conn
)
<<
'\n'
;
std
::
cout
<<
"*** accepted new connection "
<<
to_string
(
conn
)
<<
std
::
endl
;
auto
&
[
pull
,
push
]
=
event
.
data
();
auto
&
[
pull
,
push
]
=
event
.
data
();
// Subscribe the `push` end to the central merge point.
// Subscribe the `push` end to the central merge point.
messages
messages
...
@@ -72,14 +73,16 @@ void worker_impl(caf::event_based_actor* self,
...
@@ -72,14 +73,16 @@ void worker_impl(caf::event_based_actor* self,
})
})
.
subscribe
(
push
);
.
subscribe
(
push
);
// Feed messages from the `pull` end into the central merge point.
// Feed messages from the `pull` end into the central merge point.
auto
inputs
auto
inputs
//
=
pull
.
observe_on
(
self
)
=
pull
.
observe_on
(
self
)
.
do_on_error
([](
const
caf
::
error
&
err
)
{
.
do_on_error
([](
const
caf
::
error
&
err
)
{
std
::
cout
<<
"*** connection error: "
<<
to_string
(
err
)
<<
'\n'
;
std
::
cout
<<
"*** connection error: "
<<
to_string
(
err
)
<<
std
::
endl
;
})
})
.
on_error_complete
()
// Cary on if a connection breaks.
.
on_error_complete
()
// Cary on if a connection breaks.
.
do_on_complete
([
conn
]
{
.
do_on_complete
([
conn
]
{
std
::
cout
<<
"*** lost connection "
<<
to_string
(
conn
)
<<
'\n'
;
std
::
cout
<<
"*** lost connection "
<<
to_string
(
conn
)
<<
std
::
endl
;
})
})
.
map
([
conn
](
const
lp
::
frame
&
frame
)
{
.
map
([
conn
](
const
lp
::
frame
&
frame
)
{
return
message_t
{
conn
,
frame
};
return
message_t
{
conn
,
frame
};
...
...
examples/message_passing/fan_out_request.cpp
View file @
28461e75
...
@@ -142,17 +142,17 @@ void caf_main(actor_system& sys) {
...
@@ -142,17 +142,17 @@ void caf_main(actor_system& sys) {
for
(
int
row
=
0
;
row
<
rows
;
++
row
)
{
for
(
int
row
=
0
;
row
<
rows
;
++
row
)
{
for
(
int
column
=
0
;
column
<
columns
;
++
column
)
for
(
int
column
=
0
;
column
<
columns
;
++
column
)
cout
<<
std
::
setw
(
4
)
<<
f
(
get_atom_v
,
row
,
column
)
<<
' '
;
cout
<<
std
::
setw
(
4
)
<<
f
(
get_atom_v
,
row
,
column
)
<<
' '
;
cout
<<
'\n'
;
cout
<<
std
::
endl
;
}
}
// Print out AVG for each row and column.
// Print out AVG for each row and column.
for
(
int
row
=
0
;
row
<
rows
;
++
row
)
for
(
int
row
=
0
;
row
<
rows
;
++
row
)
cout
<<
"AVG(row "
<<
row
<<
") = "
cout
<<
"AVG(row "
<<
row
<<
") = "
<<
caf
::
to_string
(
f
(
get_atom_v
,
average_atom_v
,
row_atom_v
,
row
))
<<
caf
::
to_string
(
f
(
get_atom_v
,
average_atom_v
,
row_atom_v
,
row
))
<<
'\n'
;
<<
std
::
endl
;
for
(
int
column
=
0
;
column
<
columns
;
++
column
)
for
(
int
column
=
0
;
column
<
columns
;
++
column
)
cout
<<
"AVG(column "
<<
column
<<
") = "
cout
<<
"AVG(column "
<<
column
<<
") = "
<<
caf
::
to_string
(
f
(
get_atom_v
,
average_atom_v
,
column_atom_v
,
column
))
<<
caf
::
to_string
(
f
(
get_atom_v
,
average_atom_v
,
column_atom_v
,
column
))
<<
'\n'
;
<<
std
::
endl
;
}
}
CAF_MAIN
(
id_block
::
fan_out_request
)
CAF_MAIN
(
id_block
::
fan_out_request
)
examples/remoting/remote_spawn.cpp
View file @
28461e75
...
@@ -96,7 +96,7 @@ void client_repl(function_view<calculator> f) {
...
@@ -96,7 +96,7 @@ void client_repl(function_view<calculator> f) {
cout
<<
" = "
cout
<<
" = "
<<
caf
::
to_string
(
words
[
1
]
==
"+"
?
f
(
add_atom_v
,
*
x
,
*
y
)
<<
caf
::
to_string
(
words
[
1
]
==
"+"
?
f
(
add_atom_v
,
*
x
,
*
y
)
:
f
(
sub_atom_v
,
*
x
,
*
y
))
:
f
(
sub_atom_v
,
*
x
,
*
y
))
<<
"
\n
"
;
<<
std
::
endl
;
}
}
}
}
...
...
examples/web_socket/echo.cpp
View file @
28461e75
...
@@ -66,7 +66,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -66,7 +66,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
// The header parameter contains fields from the WebSocket handshake
// The header parameter contains fields from the WebSocket handshake
// such as the path and HTTP header fields..
// such as the path and HTTP header fields..
auto
path
=
acc
.
header
().
path
();
auto
path
=
acc
.
header
().
path
();
std
::
cout
<<
"*** new client request for path "
<<
path
<<
'\n'
;
std
::
cout
<<
"*** new client request for path "
<<
path
<<
std
::
endl
;
// Accept the WebSocket connection only if the path is "/".
// Accept the WebSocket connection only if the path is "/".
if
(
path
==
"/"
)
{
if
(
path
==
"/"
)
{
// Calling `accept` causes the server to acknowledge the client and
// Calling `accept` causes the server to acknowledge the client and
...
@@ -95,20 +95,20 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -95,20 +95,20 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
pull
.
observe_on
(
self
)
pull
.
observe_on
(
self
)
.
do_on_error
([](
const
caf
::
error
&
what
)
{
//
.
do_on_error
([](
const
caf
::
error
&
what
)
{
//
std
::
cout
<<
"*** connection closed: "
<<
to_string
(
what
)
std
::
cout
<<
"*** connection closed: "
<<
to_string
(
what
)
<<
"
\n
"
;
<<
std
::
endl
;
})
})
.
do_on_complete
([]
{
//
.
do_on_complete
([]
{
//
std
::
cout
<<
"*** connection closed
\n
"
;
std
::
cout
<<
"*** connection closed
"
<<
std
::
endl
;
})
})
.
do_on_next
([](
const
ws
::
frame
&
x
)
{
.
do_on_next
([](
const
ws
::
frame
&
x
)
{
if
(
x
.
is_binary
())
{
if
(
x
.
is_binary
())
{
std
::
cout
std
::
cout
<<
"*** received a binary WebSocket frame of size "
<<
"*** received a binary WebSocket frame of size "
<<
x
.
size
()
<<
'\n'
;
<<
x
.
size
()
<<
std
::
endl
;
}
else
{
}
else
{
std
::
cout
std
::
cout
<<
"*** received a text WebSocket frame of size "
<<
"*** received a text WebSocket frame of size "
<<
x
.
size
()
<<
'\n'
;
<<
x
.
size
()
<<
std
::
endl
;
}
}
})
})
.
subscribe
(
push
);
.
subscribe
(
push
);
...
...
examples/web_socket/hello-client.cpp
View file @
28461e75
...
@@ -52,7 +52,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -52,7 +52,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
// Print errors to stderr.
// Print errors to stderr.
.
do_on_error
([](
const
caf
::
error
&
what
)
{
.
do_on_error
([](
const
caf
::
error
&
what
)
{
std
::
cerr
<<
"*** error while reading from the WebSocket: "
std
::
cerr
<<
"*** error while reading from the WebSocket: "
<<
to_string
(
what
)
<<
'\n'
;
<<
to_string
(
what
)
<<
std
::
endl
;
})
})
// Restrict how many messages we receive if the user configured
// Restrict how many messages we receive if the user configured
// a limit.
// a limit.
...
@@ -65,15 +65,15 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -65,15 +65,15 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
})
})
// Print a bye-bye message if the server closes the connection.
// Print a bye-bye message if the server closes the connection.
.
do_on_complete
([]
{
//
.
do_on_complete
([]
{
//
std
::
cout
<<
"Server has closed the connection
\n
"
;
std
::
cout
<<
"Server has closed the connection
"
<<
std
::
endl
;
})
})
// Print everything from the server to stdout.
// Print everything from the server to stdout.
.
for_each
([](
const
ws
::
frame
&
msg
)
{
.
for_each
([](
const
ws
::
frame
&
msg
)
{
if
(
msg
.
is_text
())
{
if
(
msg
.
is_text
())
{
std
::
cout
<<
"Server: "
<<
msg
.
as_text
()
<<
'\n'
;
std
::
cout
<<
"Server: "
<<
msg
.
as_text
()
<<
std
::
endl
;
}
else
if
(
msg
.
is_binary
())
{
}
else
if
(
msg
.
is_binary
())
{
std
::
cout
<<
"Server: [binary message of size "
std
::
cout
<<
"Server: [binary message of size "
<<
msg
.
as_binary
().
size
()
<<
"]
\n
"
;
<<
msg
.
as_binary
().
size
()
<<
"]
"
<<
std
::
endl
;
}
}
});
});
// Send our hello message and wait until the server closes the
// Send our hello message and wait until the server closes the
...
@@ -87,7 +87,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
...
@@ -87,7 +87,7 @@ int caf_main(caf::actor_system& sys, const config& cfg) {
});
});
if
(
!
conn
)
{
if
(
!
conn
)
{
std
::
cerr
<<
"*** unable to connect to "
<<
server
->
str
()
<<
": "
std
::
cerr
<<
"*** unable to connect to "
<<
server
->
str
()
<<
": "
<<
to_string
(
conn
.
error
())
<<
'\n'
;
<<
to_string
(
conn
.
error
())
<<
std
::
endl
;
return
EXIT_FAILURE
;
return
EXIT_FAILURE
;
}
}
// Note: the actor system will keep the application running for as long as the
// Note: the actor system will keep the application running for as long as the
...
...
examples/web_socket/stock-ticker.cpp
View file @
28461e75
...
@@ -83,7 +83,7 @@ struct random_feed_state {
...
@@ -83,7 +83,7 @@ struct random_feed_state {
auto
&
x
=
update
();
auto
&
x
=
update
();
if
(
!
writer
.
apply
(
x
))
{
if
(
!
writer
.
apply
(
x
))
{
std
::
cerr
<<
"*** failed to generate JSON: "
std
::
cerr
<<
"*** failed to generate JSON: "
<<
to_string
(
writer
.
get_error
())
<<
'\n'
;
<<
to_string
(
writer
.
get_error
())
<<
std
::
endl
;
return
frame
{};
return
frame
{};
}
}
return
frame
{
writer
.
str
()};
return
frame
{
writer
.
str
()};
...
@@ -95,18 +95,19 @@ struct random_feed_state {
...
@@ -95,18 +95,19 @@ struct random_feed_state {
.
share
();
.
share
();
// Subscribe once to start the feed immediately and to keep it running.
// Subscribe once to start the feed immediately and to keep it running.
feed
.
for_each
([
n
=
1
](
const
frame
&
)
mutable
{
feed
.
for_each
([
n
=
1
](
const
frame
&
)
mutable
{
std
::
cout
<<
"*** tick "
<<
n
++
<<
"
\n
"
;
std
::
cout
<<
"*** tick "
<<
n
++
<<
std
::
endl
;
});
});
// Add each incoming WebSocket listener to the feed.
// Add each incoming WebSocket listener to the feed.
auto
n
=
std
::
make_shared
<
int
>
(
0
);
auto
n
=
std
::
make_shared
<
int
>
(
0
);
events
events
.
observe_on
(
self
)
//
.
observe_on
(
self
)
//
.
for_each
([
this
,
n
](
const
accept_event
&
ev
)
{
.
for_each
([
this
,
n
](
const
accept_event
&
ev
)
{
std
::
cout
<<
"*** added listener (n = "
<<
++*
n
<<
")
\n
"
;
std
::
cout
<<
"*** added listener (n = "
<<
++*
n
<<
")
"
<<
std
::
endl
;
auto
[
pull
,
push
]
=
ev
.
data
();
auto
[
pull
,
push
]
=
ev
.
data
();
pull
.
observe_on
(
self
)
pull
.
observe_on
(
self
)
.
do_finally
([
n
]
{
//
.
do_finally
([
n
]
{
//
std
::
cout
<<
"*** removed listener (n = "
<<
--*
n
<<
")
\n
"
;
std
::
cout
<<
"*** removed listener (n = "
<<
--*
n
<<
")"
<<
std
::
endl
;
})
})
.
subscribe
(
std
::
ignore
);
.
subscribe
(
std
::
ignore
);
feed
.
subscribe
(
push
);
feed
.
subscribe
(
push
);
...
...
libcaf_core/caf/actor_system.hpp
View file @
28461e75
...
@@ -109,6 +109,39 @@ public:
...
@@ -109,6 +109,39 @@ public:
actor_system
(
const
actor_system
&
)
=
delete
;
actor_system
(
const
actor_system
&
)
=
delete
;
actor_system
&
operator
=
(
const
actor_system
&
)
=
delete
;
actor_system
&
operator
=
(
const
actor_system
&
)
=
delete
;
/// Calls a cleanup function in its destructor for cleaning up global state.
class
[[
nodiscard
]]
global_state_guard
{
public:
using
void_fun_t
=
void
(
*
)();
explicit
global_state_guard
(
void_fun_t
f
)
:
fun_
(
f
)
{
// nop
}
global_state_guard
(
global_state_guard
&&
other
)
noexcept
:
fun_
(
other
.
fun_
)
{
other
.
fun_
=
nullptr
;
}
global_state_guard
&
operator
=
(
global_state_guard
&&
other
)
noexcept
{
std
::
swap
(
fun_
,
other
.
fun_
);
return
*
this
;
}
global_state_guard
()
=
delete
;
global_state_guard
(
const
global_state_guard
&
)
=
delete
;
global_state_guard
&
operator
=
(
const
global_state_guard
&
)
=
delete
;
~
global_state_guard
()
{
if
(
fun_
!=
nullptr
)
fun_
();
}
private:
void_fun_t
fun_
;
};
/// An (optional) component of the actor system.
/// An (optional) component of the actor system.
class
CAF_CORE_EXPORT
module
{
class
CAF_CORE_EXPORT
module
{
public:
public:
...
...
libcaf_core/caf/detail/type_traits.hpp
View file @
28461e75
...
@@ -1060,6 +1060,23 @@ template <class T>
...
@@ -1060,6 +1060,23 @@ template <class T>
constexpr
bool
is_64bit_integer_v
=
std
::
is_same_v
<
T
,
int64_t
>
constexpr
bool
is_64bit_integer_v
=
std
::
is_same_v
<
T
,
int64_t
>
||
std
::
is_same_v
<
T
,
uint64_t
>
;
||
std
::
is_same_v
<
T
,
uint64_t
>
;
/// Checks whether `T` has a static member function called `init_host_system`.
template
<
class
T
>
struct
has_init_host_system
{
template
<
class
U
>
static
auto
sfinae
(
U
*
)
->
decltype
(
U
::
init_host_system
(),
std
::
true_type
());
template
<
class
U
>
static
auto
sfinae
(...)
->
std
::
false_type
;
using
type
=
decltype
(
sfinae
<
T
>
(
nullptr
));
static
constexpr
bool
value
=
type
::
value
;
};
/// Convenience alias for `has_init_host_system<T>::value`.
template
<
class
T
>
constexpr
bool
has_init_host_system_v
=
has_init_host_system
<
T
>::
value
;
}
// namespace caf::detail
}
// namespace caf::detail
#undef CAF_HAS_MEMBER_TRAIT
#undef CAF_HAS_MEMBER_TRAIT
...
...
libcaf_core/caf/exec_main.hpp
View file @
28461e75
...
@@ -105,8 +105,28 @@ int exec_main(F fun, int argc, char** argv) {
...
@@ -105,8 +105,28 @@ int exec_main(F fun, int argc, char** argv) {
}
// namespace caf
}
// namespace caf
namespace
caf
::
detail
{
template
<
class
...
Module
>
auto
do_init_host_system
(
type_list
<
Module
...
>
,
type_list
<>
)
{
return
std
::
make_tuple
(
Module
::
init_host_system
()...);
}
template
<
class
...
Module
,
class
T
,
class
...
Ts
>
auto
do_init_host_system
(
type_list
<
Module
...
>
,
type_list
<
T
,
Ts
...
>
)
{
if
constexpr
(
detail
::
has_init_host_system_v
<
T
>
)
{
return
do_init_host_system
(
type_list
<
Module
...,
T
>
{},
type_list
<
Ts
...
>
{});
}
else
{
return
do_init_host_system
(
type_list
<
Module
...
>
{},
type_list
<
Ts
...
>
{});
}
}
}
// namespace caf::detail
#define CAF_MAIN(...) \
#define CAF_MAIN(...) \
int main(int argc, char** argv) { \
int main(int argc, char** argv) { \
[[maybe_unused]] auto host_init_guard = caf::detail::do_init_host_system( \
caf::detail::type_list<>{}, caf::detail::type_list<__VA_ARGS__>{}); \
caf::exec_main_init_meta_objects<__VA_ARGS__>(); \
caf::exec_main_init_meta_objects<__VA_ARGS__>(); \
caf::core::init_global_meta_objects(); \
caf::core::init_global_meta_objects(); \
return caf::exec_main<__VA_ARGS__>(caf_main, argc, argv); \
return caf::exec_main<__VA_ARGS__>(caf_main, argc, argv); \
...
...
libcaf_core/caf/uri.hpp
View file @
28461e75
...
@@ -38,7 +38,7 @@ public:
...
@@ -38,7 +38,7 @@ public:
/// Bundles the authority component of the URI, i.e., userinfo, host, and
/// Bundles the authority component of the URI, i.e., userinfo, host, and
/// port.
/// port.
struct
authority_type
{
struct
CAF_CORE_EXPORT
authority_type
{
std
::
string
userinfo
;
std
::
string
userinfo
;
host_type
host
;
host_type
host
;
uint16_t
port
;
uint16_t
port
;
...
...
libcaf_io/src/io/network/default_multiplexer.cpp
View file @
28461e75
...
@@ -569,9 +569,13 @@ void default_multiplexer::handle_socket_event(native_socket fd, int mask,
...
@@ -569,9 +569,13 @@ void default_multiplexer::handle_socket_event(native_socket fd, int mask,
void
default_multiplexer
::
init
()
{
void
default_multiplexer
::
init
()
{
#ifdef CAF_WINDOWS
#ifdef CAF_WINDOWS
WSADATA
WinsockData
;
// Note: when loading the caf-net module, users should call
if
(
WSAStartup
(
MAKEWORD
(
2
,
2
),
&
WinsockData
)
!=
0
)
{
// net::middleman::init_host_system() or net::this_host::startup().
CAF_CRITICAL
(
"WSAStartup failed"
);
if
(
!
system
().
has_network_manager
())
{
WSADATA
WinsockData
;
if
(
WSAStartup
(
MAKEWORD
(
2
,
2
),
&
WinsockData
)
!=
0
)
{
CAF_CRITICAL
(
"WSAStartup failed"
);
}
}
}
#endif
#endif
namespace
sr
=
defaults
::
scheduler
;
namespace
sr
=
defaults
::
scheduler
;
...
@@ -631,7 +635,8 @@ default_multiplexer::~default_multiplexer() {
...
@@ -631,7 +635,8 @@ default_multiplexer::~default_multiplexer() {
close_socket
(
pipe_reader_
.
fd
());
close_socket
(
pipe_reader_
.
fd
());
pipe_reader_
.
init
(
invalid_native_socket
);
pipe_reader_
.
init
(
invalid_native_socket
);
#ifdef CAF_WINDOWS
#ifdef CAF_WINDOWS
WSACleanup
();
if
(
!
system
().
has_network_manager
())
WSACleanup
();
#endif
#endif
}
}
...
...
libcaf_net/caf/net/middleman.hpp
View file @
28461e75
...
@@ -23,16 +23,28 @@ namespace caf::net {
...
@@ -23,16 +23,28 @@ namespace caf::net {
/// Provides a network backend for running protocol stacks.
/// Provides a network backend for running protocol stacks.
class
CAF_NET_EXPORT
middleman
:
public
actor_system
::
module
{
class
CAF_NET_EXPORT
middleman
:
public
actor_system
::
module
{
public:
public:
// -- constants --------------------------------------------------------------
/// Identifies the network manager module.
actor_system
::
module
::
id_t
id_v
=
actor_system
::
module
::
network_manager
;
// -- member types -----------------------------------------------------------
// -- member types -----------------------------------------------------------
using
module
=
actor_system
::
module
;
using
module
=
actor_system
::
module
;
using
module_ptr
=
actor_system
::
module_ptr
;
using
module_ptr
=
actor_system
::
module_ptr
;
using
void_fun_t
=
void
(
*
)();
// -- static utility functions -----------------------------------------------
// -- static utility functions -----------------------------------------------
static
void
init_global_meta_objects
();
static
void
init_global_meta_objects
();
/// Initializes global state for the network backend by calling
/// platform-dependent functions such as `WSAStartup` and `ssl::startup()`.
/// @returns a guard object shutting down the global state.
static
actor_system
::
global_state_guard
init_host_system
();
// -- constructors, destructors, and assignment operators --------------------
// -- constructors, destructors, and assignment operators --------------------
explicit
middleman
(
actor_system
&
sys
);
explicit
middleman
(
actor_system
&
sys
);
...
...
libcaf_net/caf/net/web_socket/upper_layer.hpp
View file @
28461e75
...
@@ -29,7 +29,7 @@ public:
...
@@ -29,7 +29,7 @@ public:
virtual
error
start
(
lower_layer
*
down
)
=
0
;
virtual
error
start
(
lower_layer
*
down
)
=
0
;
};
};
class
upper_layer
::
server
:
public
upper_layer
{
class
CAF_NET_EXPORT
upper_layer
::
server
:
public
upper_layer
{
public:
public:
virtual
~
server
();
virtual
~
server
();
...
...
libcaf_net/src/net/middleman.cpp
View file @
28461e75
...
@@ -9,8 +9,10 @@
...
@@ -9,8 +9,10 @@
#include "caf/expected.hpp"
#include "caf/expected.hpp"
#include "caf/net/http/with.hpp"
#include "caf/net/http/with.hpp"
#include "caf/net/prometheus.hpp"
#include "caf/net/prometheus.hpp"
#include "caf/net/ssl/startup.hpp"
#include "caf/net/tcp_accept_socket.hpp"
#include "caf/net/tcp_accept_socket.hpp"
#include "caf/net/tcp_stream_socket.hpp"
#include "caf/net/tcp_stream_socket.hpp"
#include "caf/net/this_host.hpp"
#include "caf/raise_error.hpp"
#include "caf/raise_error.hpp"
#include "caf/sec.hpp"
#include "caf/sec.hpp"
#include "caf/send.hpp"
#include "caf/send.hpp"
...
@@ -57,6 +59,15 @@ void middleman::init_global_meta_objects() {
...
@@ -57,6 +59,15 @@ void middleman::init_global_meta_objects() {
// nop
// nop
}
}
actor_system
::
global_state_guard
middleman
::
init_host_system
()
{
this_host
::
startup
();
ssl
::
startup
();
return
actor_system
::
global_state_guard
{
+
[]
{
ssl
::
cleanup
();
this_host
::
cleanup
();
}};
}
middleman
::
middleman
(
actor_system
&
sys
)
middleman
::
middleman
(
actor_system
&
sys
)
:
sys_
(
sys
),
mpx_
(
multiplexer
::
make
(
this
))
{
:
sys_
(
sys
),
mpx_
(
multiplexer
::
make
(
this
))
{
// nop
// nop
...
...
manual/net/Overview.rst
View file @
28461e75
...
@@ -10,6 +10,26 @@ and assembling protocol stacks.
...
@@ -10,6 +10,26 @@ and assembling protocol stacks.
When using caf-net for applications, we generally recommend sticking to the
When using caf-net for applications, we generally recommend sticking to the
declarative API.
declarative API.
Initializing the Module
-----------------------
The networking module is an optional component of CAF. To use it, users can pass
``caf::net::middleman`` to ``CAF_MAIN``.
When not using the ``CAF_MAIN`` macro, users must initialize the library by:
- Calling ``caf::net::middleman::init_global_meta_objects()`` before
initializing the ``actor_system``. This step adds the necessary meta objects
to the global meta object registry.
- Calling ``caf::net::middleman::init_host_system()`` before initializing the
``actor_system`` (or calling any function of the module). This step runs
platform-specific initialization code (such as calling ``WSAStartup`` on
Windows) by calling ``caf::net::this_host::startup()`` and initializes the SSL
library by calling ``caf::net::ssl::startup()`` The function
``init_host_system`` returns a guard object that calls
``caf::net::this_host::cleanup()`` and ``caf::net::ssl::cleanup()`` in its
destructor.
Declarative High-level DSL :sup:`experimental`
Declarative High-level DSL :sup:`experimental`
----------------------------------------------
----------------------------------------------
...
...
robot/http/rest.robot
View file @
28461e75
...
@@ -49,16 +49,13 @@ HTTPS Test Delete Key Value Pair
...
@@ -49,16 +49,13 @@ HTTPS Test Delete Key Value Pair
*** Keywords ***
*** Keywords ***
Start Servers
Start Servers
${res1}
=
Start Process
${BINARY_PATH}
-p
55501
Start Process
${BINARY_PATH}
-p
55501
Set Suite Variable
${http_server_process}
${res1}
Start Process
${BINARY_PATH}
-p
55502
-k
${SSL_PATH}
/key.pem
-c
${SSL_PATH}
/cert.pem
${res2}
=
Start Process
${BINARY_PATH}
-p
55502
-k
${SSL_PATH}
/key.pem
-c
${SSL_PATH}
/cert.pem
Set Suite Variable
${https_server_process}
${res2}
Wait Until Keyword Succeeds
5s
125ms
Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTPS Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTPS Server Is Reachable
Stop Servers
Stop Servers
Terminate Process
${http_server_process}
Run Keyword And Ignore Error
Terminate All Processes
Terminate Process
${https_server_process}
Check If HTTP Server Is Reachable
Check If HTTP Server Is Reachable
Log
Try reaching
${HTTP_URL}
/status.
Log
Try reaching
${HTTP_URL}
/status.
...
...
robot/web_socket/echo.robot
View file @
28461e75
...
@@ -9,10 +9,10 @@ Suite Setup Start Servers
...
@@ -9,10 +9,10 @@ Suite Setup Start Servers
Suite Teardown
Stop Servers
Suite Teardown
Stop Servers
*** Variables ***
*** Variables ***
${HTTP_URL}
http://localhost:5550
1
${HTTP_URL}
http://localhost:5550
3
${HTTPS_URL}
https://localhost:5550
2
${HTTPS_URL}
https://localhost:5550
4
${WS_URL}
ws://localhost:5550
1
${WS_URL}
ws://localhost:5550
3
${WSS_URL}
wss://localhost:5550
2
${WSS_URL}
wss://localhost:5550
4
${FRAME_COUNT}
${10}
${FRAME_COUNT}
${10}
${BINARY_PATH}
/path/to/the/server
${BINARY_PATH}
/path/to/the/server
${SSL_PATH}
/path/to/the/pem/files
${SSL_PATH}
/path/to/the/pem/files
...
@@ -37,16 +37,13 @@ Test WebSocket Over SSL Server
...
@@ -37,16 +37,13 @@ Test WebSocket Over SSL Server
*** Keywords ***
*** Keywords ***
Start Servers
Start Servers
${res1}
=
Start Process
${BINARY_PATH}
-p
55501
Start Process
${BINARY_PATH}
-p
55503
Set Suite Variable
${ws_server_process}
${res1}
Start Process
${BINARY_PATH}
-p
55504
-k
${SSL_PATH}
/key.pem
-c
${SSL_PATH}
/cert.pem
${res2}
=
Start Process
${BINARY_PATH}
-p
55502
-k
${SSL_PATH}
/key.pem
-c
${SSL_PATH}
/cert.pem
Set Suite Variable
${wss_server_process}
${res2}
Wait Until Keyword Succeeds
5s
125ms
Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTPS Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTPS Server Is Reachable
Stop Servers
Stop Servers
Terminate Process
${ws_server_process}
Run Keyword And Ignore Error
Terminate All Processes
Terminate Process
${wss_server_process}
Check If HTTP Server Is Reachable
Check If HTTP Server Is Reachable
# The server sends a "400 Bad Request" if we try HTTP on the WebSocket port.
# The server sends a "400 Bad Request" if we try HTTP on the WebSocket port.
...
...
robot/web_socket/quote-server.robot
View file @
28461e75
...
@@ -9,10 +9,10 @@ Suite Setup Start Servers
...
@@ -9,10 +9,10 @@ Suite Setup Start Servers
Suite Teardown
Stop Servers
Suite Teardown
Stop Servers
*** Variables ***
*** Variables ***
${HTTP_URL}
http://localhost:5550
1
${HTTP_URL}
http://localhost:5550
5
${HTTPS_URL}
https://localhost:5550
2
${HTTPS_URL}
https://localhost:5550
6
${WS_URL}
ws://localhost:5550
1
/ws/quotes/seneca
${WS_URL}
ws://localhost:5550
5
/ws/quotes/seneca
${WSS_URL}
wss://localhost:5550
2
/ws/quotes/seneca
${WSS_URL}
wss://localhost:5550
6
/ws/quotes/seneca
${FRAME_COUNT}
${10}
${FRAME_COUNT}
${10}
${BINARY_PATH}
/path/to/the/server
${BINARY_PATH}
/path/to/the/server
${SSL_PATH}
/path/to/the/pem/files
${SSL_PATH}
/path/to/the/pem/files
...
@@ -45,16 +45,13 @@ Test WebSocket Over SSL Server Quotes
...
@@ -45,16 +45,13 @@ Test WebSocket Over SSL Server Quotes
*** Keywords ***
*** Keywords ***
Start Servers
Start Servers
${res1}
=
Start Process
${BINARY_PATH}
-p
55501
Start Process
${BINARY_PATH}
-p
55505
Set Suite Variable
${ws_server_process}
${res1}
Start Process
${BINARY_PATH}
-p
55506
-k
${SSL_PATH}
/key.pem
-c
${SSL_PATH}
/cert.pem
${res2}
=
Start Process
${BINARY_PATH}
-p
55502
-k
${SSL_PATH}
/key.pem
-c
${SSL_PATH}
/cert.pem
Set Suite Variable
${wss_server_process}
${res2}
Wait Until Keyword Succeeds
5s
125ms
Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTP Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTPS Server Is Reachable
Wait Until Keyword Succeeds
5s
125ms
Check If HTTPS Server Is Reachable
Stop Servers
Stop Servers
Terminate Process
${ws_server_process}
Run Keyword And Ignore Error
Terminate All Processes
Terminate Process
${wss_server_process}
Check If HTTP Server Is Reachable
Check If HTTP Server Is Reachable
Log
Try reaching
${HTTP_URL}
/status.
Log
Try reaching
${HTTP_URL}
/status.
...
...
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