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
b24836ec
Commit
b24836ec
authored
Aug 16, 2023
by
Samir Halilcevic
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Pull out masking in web_socket framing layer
parent
2cbfa145
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
62 additions
and
30 deletions
+62
-30
libcaf_net/caf/detail/rfc6455.cpp
libcaf_net/caf/detail/rfc6455.cpp
+5
-4
libcaf_net/caf/detail/rfc6455.hpp
libcaf_net/caf/detail/rfc6455.hpp
+2
-2
libcaf_net/caf/detail/rfc6455.test.cpp
libcaf_net/caf/detail/rfc6455.test.cpp
+17
-1
libcaf_net/caf/net/web_socket/framing.cpp
libcaf_net/caf/net/web_socket/framing.cpp
+28
-15
libcaf_net/tests/legacy/net/web_socket/framing.cpp
libcaf_net/tests/legacy/net/web_socket/framing.cpp
+10
-8
No files found.
libcaf_net/caf/detail/rfc6455.cpp
View file @
b24836ec
...
@@ -10,15 +10,16 @@
...
@@ -10,15 +10,16 @@
namespace
caf
::
detail
{
namespace
caf
::
detail
{
void
rfc6455
::
mask_data
(
uint32_t
key
,
span
<
char
>
data
)
{
void
rfc6455
::
mask_data
(
uint32_t
key
,
span
<
char
>
data
,
size_t
skip
)
{
mask_data
(
key
,
as_writable_bytes
(
data
));
mask_data
(
key
,
as_writable_bytes
(
data
)
,
skip
);
}
}
void
rfc6455
::
mask_data
(
uint32_t
key
,
byte_span
data
)
{
void
rfc6455
::
mask_data
(
uint32_t
key
,
byte_span
data
,
size_t
skip
)
{
auto
no_key
=
to_network_order
(
key
);
auto
no_key
=
to_network_order
(
key
);
std
::
byte
arr
[
4
];
std
::
byte
arr
[
4
];
memcpy
(
arr
,
&
no_key
,
4
);
memcpy
(
arr
,
&
no_key
,
4
);
size_t
i
=
0
;
data
=
data
.
subspan
(
skip
);
size_t
i
=
skip
%
4
;
for
(
auto
&
x
:
data
)
{
for
(
auto
&
x
:
data
)
{
x
=
x
^
arr
[
i
];
x
=
x
^
arr
[
i
];
i
=
(
i
+
1
)
%
4
;
i
=
(
i
+
1
)
%
4
;
...
...
libcaf_net/caf/detail/rfc6455.hpp
View file @
b24836ec
...
@@ -42,9 +42,9 @@ struct CAF_NET_EXPORT rfc6455 {
...
@@ -42,9 +42,9 @@ struct CAF_NET_EXPORT rfc6455 {
// -- utility functions ------------------------------------------------------
// -- utility functions ------------------------------------------------------
static
void
mask_data
(
uint32_t
key
,
span
<
char
>
data
);
static
void
mask_data
(
uint32_t
key
,
span
<
char
>
data
,
size_t
skip
=
0
);
static
void
mask_data
(
uint32_t
key
,
byte_span
data
);
static
void
mask_data
(
uint32_t
key
,
byte_span
data
,
size_t
skip
=
0
);
static
void
assemble_frame
(
uint32_t
mask_key
,
span
<
const
char
>
data
,
static
void
assemble_frame
(
uint32_t
mask_key
,
span
<
const
char
>
data
,
byte_buffer
&
out
);
byte_buffer
&
out
);
...
...
libcaf_net/caf/detail/rfc6455.test.cpp
View file @
b24836ec
...
@@ -32,7 +32,7 @@ auto take(const T& xs, size_t num_bytes) {
...
@@ -32,7 +32,7 @@ auto take(const T& xs, size_t num_bytes) {
return
std
::
vector
<
typename
T
::
value_type
>
{
xs
.
begin
(),
xs
.
begin
()
+
n
};
return
std
::
vector
<
typename
T
::
value_type
>
{
xs
.
begin
(),
xs
.
begin
()
+
n
};
}
}
TEST
(
"masking"
)
{
TEST
(
"masking
the full payload
"
)
{
auto
key
=
uint32_t
{
0xDEADC0DE
};
auto
key
=
uint32_t
{
0xDEADC0DE
};
auto
data
=
bytes
({
0x12
,
0x34
,
0x45
,
0x67
,
0x89
,
0x9A
});
auto
data
=
bytes
({
0x12
,
0x34
,
0x45
,
0x67
,
0x89
,
0x9A
});
SECTION
(
"masking XORs the repeated key to data"
)
{
SECTION
(
"masking XORs the repeated key to data"
)
{
...
@@ -55,6 +55,22 @@ TEST("masking") {
...
@@ -55,6 +55,22 @@ TEST("masking") {
}
}
}
}
TEST
(
"partial making with offset"
)
{
using
namespace
std
::
literals
;
auto
key
=
uint32_t
{
0xDEADC0DE
};
auto
original_data
=
std
::
string
{
"Hello, world!"
};
auto
masked_data
=
original_data
;
impl
::
mask_data
(
key
,
make_span
(
masked_data
));
for
(
auto
i
=
0ul
;
i
<
original_data
.
size
();
i
++
)
{
auto
uut
=
original_data
;
impl
::
mask_data
(
key
,
make_span
(
uut
),
i
);
check_eq
(
std
::
string_view
{
uut
}.
substr
(
0
,
i
),
std
::
string_view
{
original_data
}.
substr
(
0
,
i
));
check_eq
(
std
::
string_view
{
uut
}.
substr
(
i
),
std
::
string_view
{
masked_data
}.
substr
(
i
));
}
}
TEST
(
"decoding a frame with RSV bits fails"
)
{
TEST
(
"decoding a frame with RSV bits fails"
)
{
std
::
vector
<
uint8_t
>
data
;
std
::
vector
<
uint8_t
>
data
;
byte_buffer
out
=
bytes
({
byte_buffer
out
=
bytes
({
...
...
libcaf_net/caf/net/web_socket/framing.cpp
View file @
b24836ec
...
@@ -63,9 +63,10 @@ void framing::abort(const error& reason) {
...
@@ -63,9 +63,10 @@ void framing::abort(const error& reason) {
up_
->
abort
(
reason
);
up_
->
abort
(
reason
);
}
}
ptrdiff_t
framing
::
consume
(
byte_span
buffer
,
byte_span
)
{
ptrdiff_t
framing
::
consume
(
byte_span
buffer
,
byte_span
delta
)
{
// Make sure we're overriding any 'exactly' setting.
// Make sure we're overriding any 'exactly' setting.
down_
->
configure_read
(
receive_policy
::
up_to
(
2048
));
down_
->
configure_read
(
receive_policy
::
up_to
(
2048
));
// Parse header.
// Parse header.
detail
::
rfc6455
::
header
hdr
;
detail
::
rfc6455
::
header
hdr
;
auto
hdr_bytes
=
detail
::
rfc6455
::
decode_header
(
buffer
,
hdr
);
auto
hdr_bytes
=
detail
::
rfc6455
::
decode_header
(
buffer
,
hdr
);
...
@@ -103,20 +104,39 @@ ptrdiff_t framing::consume(byte_span buffer, byte_span) {
...
@@ -103,20 +104,39 @@ ptrdiff_t framing::consume(byte_span buffer, byte_span) {
return
-
1
;
return
-
1
;
}
}
}
}
// Wait for more data if necessary.
size_t
frame_size
=
hdr_bytes
+
hdr
.
payload_len
;
size_t
frame_size
=
hdr_bytes
+
hdr
.
payload_len
;
// unmask the arrived data
if
(
hdr
.
mask_key
!=
0
)
{
// leave out the header part
// leave out the already part
auto
offset
=
static_cast
<
ptrdiff_t
>
(
buffer
.
size
()
-
delta
.
size
())
-
hdr_bytes
;
// if the delta buffer is empty this means that we got called to the framing
// layer, consumed one frame and returned with unconsumed bytes that
// represent the second frame and the transport layer called us again, so
// even though we saw the bytes beofre, we didn't unmask them.
if
(
delta
.
empty
())
offset
=
0
;
if
(
offset
<
0
)
offset
=
0
;
auto
payload
=
buffer
;
if
(
buffer
.
size
()
>
frame_size
)
payload
=
buffer
.
subspan
(
0
,
frame_size
);
detail
::
rfc6455
::
mask_data
(
hdr
.
mask_key
,
payload
.
subspan
(
hdr_bytes
),
offset
);
}
// Wait for more data if necessary.
if
(
buffer
.
size
()
<
frame_size
)
{
if
(
buffer
.
size
()
<
frame_size
)
{
// when handling a text frame we want to fail early on invalid UTF-8
// when handling a text frame we want to fail early on invalid UTF-8
if
(
hdr
.
opcode
==
detail
::
rfc6455
::
text_frame
if
(
hdr
.
opcode
==
detail
::
rfc6455
::
text_frame
||
opcode_
==
detail
::
rfc6455
::
text_frame
)
{
||
opcode_
==
detail
::
rfc6455
::
text_frame
)
{
down_
->
configure_read
(
down_
->
configure_read
(
receive_policy
::
up_to
(
frame_size
));
receive_policy
::
between
(
buffer
.
size
()
+
1
,
frame_size
));
if
(
hdr
.
opcode
==
detail
::
rfc6455
::
text_frame
)
{
if
(
hdr
.
opcode
==
detail
::
rfc6455
::
text_frame
)
{
auto
arrived_payload
auto
arrived_payload
=
std
::
vector
<
std
::
byte
>
{
buffer
.
begin
()
+
hdr_bytes
,
buffer
.
end
()};
=
std
::
vector
<
std
::
byte
>
{
buffer
.
begin
()
+
hdr_bytes
,
buffer
.
end
()};
if
(
hdr
.
mask_key
!=
0
)
{
detail
::
rfc6455
::
mask_data
(
hdr
.
mask_key
,
arrived_payload
);
}
if
(
auto
[
index
,
incomplete
]
if
(
auto
[
index
,
incomplete
]
=
detail
::
rfc3629
::
validate
(
arrived_payload
);
=
detail
::
rfc3629
::
validate
(
arrived_payload
);
index
!=
arrived_payload
.
size
()
&&
!
incomplete
)
{
index
!=
arrived_payload
.
size
()
&&
!
incomplete
)
{
...
@@ -129,11 +149,6 @@ ptrdiff_t framing::consume(byte_span buffer, byte_span) {
...
@@ -129,11 +149,6 @@ ptrdiff_t framing::consume(byte_span buffer, byte_span) {
payload_buf_
.
end
()};
payload_buf_
.
end
()};
unvalidated_payload
.
insert
(
unvalidated_payload
.
end
(),
unvalidated_payload
.
insert
(
unvalidated_payload
.
end
(),
buffer
.
begin
()
+
hdr_bytes
,
buffer
.
end
());
buffer
.
begin
()
+
hdr_bytes
,
buffer
.
end
());
if
(
hdr
.
mask_key
!=
0
)
{
detail
::
rfc6455
::
mask_data
(
hdr
.
mask_key
,
make_span
(
unvalidated_payload
)
.
subspan
(
payload_buf_
.
size
()
-
validation_offset_
));
}
if
(
auto
[
index
,
incomplete
]
if
(
auto
[
index
,
incomplete
]
=
detail
::
rfc3629
::
validate
(
unvalidated_payload
);
=
detail
::
rfc3629
::
validate
(
unvalidated_payload
);
index
!=
unvalidated_payload
.
size
()
&&
!
incomplete
)
{
index
!=
unvalidated_payload
.
size
()
&&
!
incomplete
)
{
...
@@ -146,12 +161,10 @@ ptrdiff_t framing::consume(byte_span buffer, byte_span) {
...
@@ -146,12 +161,10 @@ ptrdiff_t framing::consume(byte_span buffer, byte_span) {
}
}
return
0
;
return
0
;
}
}
// Decode frame.
// Decode frame.
auto
payload_len
=
static_cast
<
size_t
>
(
hdr
.
payload_len
);
auto
payload_len
=
static_cast
<
size_t
>
(
hdr
.
payload_len
);
auto
payload
=
buffer
.
subspan
(
hdr_bytes
,
payload_len
);
auto
payload
=
buffer
.
subspan
(
hdr_bytes
,
payload_len
);
if
(
hdr
.
mask_key
!=
0
)
{
detail
::
rfc6455
::
mask_data
(
hdr
.
mask_key
,
payload
);
}
// Handle control frames first, since these may not me fragmented,
// Handle control frames first, since these may not me fragmented,
// and can arrive between regular message fragments.
// and can arrive between regular message fragments.
if
(
detail
::
rfc6455
::
is_control_frame
(
hdr
.
opcode
))
{
if
(
detail
::
rfc6455
::
is_control_frame
(
hdr
.
opcode
))
{
...
...
libcaf_net/tests/legacy/net/web_socket/framing.cpp
View file @
b24836ec
...
@@ -381,15 +381,16 @@ SCENARIO("the application shuts down on invalid UTF-8 message") {
...
@@ -381,15 +381,16 @@ SCENARIO("the application shuts down on invalid UTF-8 message") {
WHEN
(
"the client sends an invalid text frame byte by byte"
)
{
WHEN
(
"the client sends an invalid text frame byte by byte"
)
{
reset
();
reset
();
byte_buffer
frame
;
byte_buffer
frame
;
detail
::
rfc6455
::
assemble_frame
(
detail
::
rfc6455
::
text_frame
,
0x0
,
detail
::
rfc6455
::
mask_data
(
0xDEADC0DE
,
data
);
detail
::
rfc6455
::
assemble_frame
(
detail
::
rfc6455
::
text_frame
,
0xDEADC0DE
,
data_span
,
frame
,
0
);
data_span
,
frame
,
0
);
for
(
auto
i
=
0
;
i
<
1
4
;
i
++
)
{
for
(
auto
i
=
0
;
i
<
1
8
;
i
++
)
{
transport
->
push
(
make_span
(
frame
).
subspan
(
i
,
1
));
transport
->
push
(
make_span
(
frame
).
subspan
(
i
,
1
));
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK
(
!
app
->
has_aborted
());
CHECK
(
!
app
->
has_aborted
());
}
}
THEN
(
"the server aborts when receiving the invalid byte"
)
{
THEN
(
"the server aborts when receiving the invalid byte"
)
{
transport
->
push
(
make_span
(
frame
).
subspan
(
1
4
,
1
));
transport
->
push
(
make_span
(
frame
).
subspan
(
1
8
,
1
));
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK_EQ
(
app
->
abort_reason
,
sec
::
malformed_message
);
CHECK_EQ
(
app
->
abort_reason
,
sec
::
malformed_message
);
CHECK_EQ
(
fetch_status
(
transport
->
output_buffer
()),
CHECK_EQ
(
fetch_status
(
transport
->
output_buffer
()),
...
@@ -399,8 +400,8 @@ SCENARIO("the application shuts down on invalid UTF-8 message") {
...
@@ -399,8 +400,8 @@ SCENARIO("the application shuts down on invalid UTF-8 message") {
WHEN
(
"the client sends the first frame of a text messagee"
)
{
WHEN
(
"the client sends the first frame of a text messagee"
)
{
reset
();
reset
();
byte_buffer
frame
;
byte_buffer
frame
;
detail
::
rfc6455
::
assemble_frame
(
detail
::
rfc6455
::
text_frame
,
0x
0
,
detail
::
rfc6455
::
assemble_frame
(
detail
::
rfc6455
::
text_frame
,
0x
DEADC0DE
,
data_span
.
subspan
(
0
,
6
),
frame
,
0
);
data_span
.
subspan
(
0
,
8
),
frame
,
0
);
transport
->
push
(
frame
);
transport
->
push
(
frame
);
CHECK_EQ
(
transport
->
handle_input
(),
CHECK_EQ
(
transport
->
handle_input
(),
static_cast
<
ptrdiff_t
>
(
frame
.
size
()));
static_cast
<
ptrdiff_t
>
(
frame
.
size
()));
...
@@ -409,14 +410,15 @@ SCENARIO("the application shuts down on invalid UTF-8 message") {
...
@@ -409,14 +410,15 @@ SCENARIO("the application shuts down on invalid UTF-8 message") {
AND_WHEN
(
"sending the invalid continuation frame byte by byte"
)
{
AND_WHEN
(
"sending the invalid continuation frame byte by byte"
)
{
byte_buffer
frame
;
byte_buffer
frame
;
detail
::
rfc6455
::
assemble_frame
(
detail
::
rfc6455
::
continuation_frame
,
detail
::
rfc6455
::
assemble_frame
(
detail
::
rfc6455
::
continuation_frame
,
0x0
,
data_span
.
subspan
(
6
),
frame
);
0xDEADC0DE
,
data_span
.
subspan
(
8
),
for
(
auto
i
=
0
;
i
<
8
;
i
++
)
{
frame
);
for
(
auto
i
=
0
;
i
<
10
;
i
++
)
{
transport
->
push
(
make_span
(
frame
).
subspan
(
i
,
1
));
transport
->
push
(
make_span
(
frame
).
subspan
(
i
,
1
));
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK
(
!
app
->
has_aborted
());
CHECK
(
!
app
->
has_aborted
());
}
}
THEN
(
"the server aborts the application on the invalid byte"
)
{
THEN
(
"the server aborts the application on the invalid byte"
)
{
transport
->
push
(
make_span
(
frame
).
subspan
(
8
,
1
));
transport
->
push
(
make_span
(
frame
).
subspan
(
10
,
1
));
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK_EQ
(
transport
->
handle_input
(),
0
);
CHECK_EQ
(
app
->
abort_reason
,
sec
::
malformed_message
);
CHECK_EQ
(
app
->
abort_reason
,
sec
::
malformed_message
);
CHECK_EQ
(
fetch_status
(
transport
->
output_buffer
()),
CHECK_EQ
(
fetch_status
(
transport
->
output_buffer
()),
...
...
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