Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
Runtime
提交
375a15ba
R
Runtime
项目概览
jobily
/
Runtime
11 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Runtime
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
375a15ba
编写于
1月 22, 2020
作者:
S
Stephen Toub
提交者:
GitHub
1月 22, 2020
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Improve error messages for invalid WebSocket headers (#1962)
And add tests.
上级
47ab0dc0
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
115 addition
and
15 deletion
+115
-15
src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs
...ries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs
+34
-15
src/libraries/Common/tests/System/Net/WebSockets/WebSocketCreateTest.cs
...Common/tests/System/Net/WebSockets/WebSocketCreateTest.cs
+45
-0
src/libraries/System.Net.WebSockets.WebSocketProtocol/src/Resources/Strings.resx
...t.WebSockets.WebSocketProtocol/src/Resources/Strings.resx
+18
-0
src/libraries/System.Net.WebSockets/src/Resources/Strings.resx
...ibraries/System.Net.WebSockets/src/Resources/Strings.resx
+18
-0
未找到文件。
src/libraries/Common/src/System/Net/WebSockets/ManagedWebSocket.cs
浏览文件 @
375a15ba
...
...
@@ -666,9 +666,10 @@ private static int WriteHeader(MessageOpcode opcode, byte[] sendBuffer, ReadOnly
}
}
if
(!
TryParseMessageHeaderFromReceiveBuffer
(
out
header
))
string
headerErrorMessage
=
TryParseMessageHeaderFromReceiveBuffer
(
out
header
);
if
(
headerErrorMessage
!=
null
)
{
await
CloseWithReceiveErrorAndThrowAsync
(
WebSocketCloseStatus
.
ProtocolError
,
WebSocketError
.
Faulted
).
ConfigureAwait
(
false
);
await
CloseWithReceiveErrorAndThrowAsync
(
WebSocketCloseStatus
.
ProtocolError
,
WebSocketError
.
Faulted
,
headerErrorMessage
).
ConfigureAwait
(
false
);
}
_receivedMaskOffsetOffset
=
0
;
}
...
...
@@ -770,6 +771,12 @@ private static int WriteHeader(MessageOpcode opcode, byte[] sendBuffer, ReadOnly
throw
new
OperationCanceledException
(
nameof
(
WebSocketState
.
Aborted
),
exc
);
}
_abortSource
.
Cancel
();
if
(
exc
is
WebSocketException
)
{
throw
;
}
throw
new
WebSocketException
(
WebSocketError
.
ConnectionClosedPrematurely
,
exc
);
}
finally
...
...
@@ -831,7 +838,7 @@ private async ValueTask HandleReceivedCloseAsync(MessageHeader header, Cancellat
}
catch
(
DecoderFallbackException
exc
)
{
await
CloseWithReceiveErrorAndThrowAsync
(
WebSocketCloseStatus
.
ProtocolError
,
WebSocketError
.
Faulted
,
exc
).
ConfigureAwait
(
false
);
await
CloseWithReceiveErrorAndThrowAsync
(
WebSocketCloseStatus
.
ProtocolError
,
WebSocketError
.
Faulted
,
innerException
:
exc
).
ConfigureAwait
(
false
);
}
}
ConsumeFromBuffer
((
int
)
header
.
PayloadLength
);
...
...
@@ -947,9 +954,10 @@ private static bool IsValidCloseStatus(WebSocketCloseStatus closeStatus)
/// <summary>Send a close message to the server and throw an exception, in response to getting bad data from the server.</summary>
/// <param name="closeStatus">The close status code to use.</param>
/// <param name="error">The error reason.</param>
/// <param name="errorMessage">An optional error message to include in the thrown exception.</param>
/// <param name="innerException">An optional inner exception to include in the thrown exception.</param>
private
async
ValueTask
CloseWithReceiveErrorAndThrowAsync
(
WebSocketCloseStatus
closeStatus
,
WebSocketError
error
,
Exception
innerException
=
null
)
WebSocketCloseStatus
closeStatus
,
WebSocketError
error
,
string
errorMessage
=
null
,
Exception
innerException
=
null
)
{
// Close the connection if it hasn't already been closed
if
(!
_sentCloseFrame
)
...
...
@@ -961,13 +969,15 @@ private static bool IsValidCloseStatus(WebSocketCloseStatus closeStatus)
_receiveBufferCount
=
0
;
// Let the caller know we've failed
throw
new
WebSocketException
(
error
,
innerException
);
throw
errorMessage
!=
null
?
new
WebSocketException
(
error
,
errorMessage
,
innerException
)
:
new
WebSocketException
(
error
,
innerException
);
}
/// <summary>Parses a message header from the buffer. This assumes the header is in the buffer.</summary>
/// <param name="resultHeader">The read header.</param>
/// <returns>
true if a header was read; fal
se if the header was invalid.</returns>
private
bool
TryParseMessageHeaderFromReceiveBuffer
(
out
MessageHeader
resultHeader
)
/// <returns>
null if a valid header was read; non-null containing the string error message to u
se if the header was invalid.</returns>
private
string
TryParseMessageHeaderFromReceiveBuffer
(
out
MessageHeader
resultHeader
)
{
Debug
.
Assert
(
_receiveBufferCount
>=
2
,
$"Expected to at least have the first two bytes of the header."
);
...
...
@@ -1001,12 +1011,18 @@ private bool TryParseMessageHeaderFromReceiveBuffer(out MessageHeader resultHead
ConsumeFromBuffer
(
8
);
}
bool
shouldFail
=
reservedSet
;
if
(
reservedSet
)
{
resultHeader
=
default
;
return
SR
.
net_Websockets_ReservedBitsSet
;
}
if
(
masked
)
{
if
(!
_isServer
)
{
shouldFail
=
true
;
resultHeader
=
default
;
return
SR
.
net_Websockets_ClientReceivedMaskedFrame
;
}
header
.
Mask
=
CombineMaskBytes
(
receiveBufferSpan
,
_receiveBufferOffset
);
...
...
@@ -1021,7 +1037,8 @@ private bool TryParseMessageHeaderFromReceiveBuffer(out MessageHeader resultHead
if
(
_lastReceiveHeader
.
Fin
)
{
// Can't continue from a final message
shouldFail
=
true
;
resultHeader
=
default
;
return
SR
.
net_Websockets_ContinuationFromFinalFrame
;
}
break
;
...
...
@@ -1030,7 +1047,8 @@ private bool TryParseMessageHeaderFromReceiveBuffer(out MessageHeader resultHead
if
(!
_lastReceiveHeader
.
Fin
)
{
// Must continue from a non-final message
shouldFail
=
true
;
resultHeader
=
default
;
return
SR
.
net_Websockets_NonContinuationAfterNonFinalFrame
;
}
break
;
...
...
@@ -1040,19 +1058,20 @@ private bool TryParseMessageHeaderFromReceiveBuffer(out MessageHeader resultHead
if
(
header
.
PayloadLength
>
MaxControlPayloadLength
||
!
header
.
Fin
)
{
// Invalid control messgae
shouldFail
=
true
;
resultHeader
=
default
;
return
SR
.
net_Websockets_InvalidControlMessage
;
}
break
;
default
:
// Unknown opcode
shouldFail
=
true
;
break
;
resultHeader
=
default
;
return
SR
.
Format
(
SR
.
net_Websockets_UnknownOpcode
,
header
.
Opcode
)
;
}
// Return the read header
resultHeader
=
header
;
return
!
shouldFai
l
;
return
nul
l
;
}
/// <summary>Send a close message, then receive until we get a close response message.</summary>
...
...
src/libraries/Common/tests/System/Net/WebSockets/WebSocketCreateTest.cs
浏览文件 @
375a15ba
...
...
@@ -101,6 +101,51 @@ public async Task ReceiveAsync_UTF8SplitAcrossMultipleBuffers_ValidDataReceived(
}
}
[
Theory
]
[
InlineData
(
0
b_1000_0001
,
0
b_0_000_0001
,
false
)]
// fin + text, no mask + length == 1
[
InlineData
(
0
b_1100_0001
,
0
b_0_000_0001
,
true
)]
// fin + rsv1 + text, no mask + length == 1
[
InlineData
(
0
b_1010_0001
,
0
b_0_000_0001
,
true
)]
// fin + rsv2 + text, no mask + length == 1
[
InlineData
(
0
b_1001_0001
,
0
b_0_000_0001
,
true
)]
// fin + rsv3 + text, no mask + length == 1
[
InlineData
(
0
b_1111_0001
,
0
b_0_000_0001
,
true
)]
// fin + rsv1 + rsv2 + rsv3 + text, no mask + length == 1
[
InlineData
(
0
b_1000_0001
,
0
b_1_000_0001
,
true
)]
// fin + text, mask + length == 1
[
InlineData
(
0
b_1000_0011
,
0
b_0_000_0001
,
true
)]
// fin + opcode==3, no mask + length == 1
[
InlineData
(
0
b_1000_0100
,
0
b_0_000_0001
,
true
)]
// fin + opcode==4, no mask + length == 1
[
InlineData
(
0
b_1000_0101
,
0
b_0_000_0001
,
true
)]
// fin + opcode==5, no mask + length == 1
[
InlineData
(
0
b_1000_0110
,
0
b_0_000_0001
,
true
)]
// fin + opcode==6, no mask + length == 1
[
InlineData
(
0
b_1000_0111
,
0
b_0_000_0001
,
true
)]
// fin + opcode==7, no mask + length == 1
public
async
Task
ReceiveAsync_InvalidFrameHeader_AbortsAndThrowsException
(
byte
firstByte
,
byte
secondByte
,
bool
shouldFail
)
{
using
(
Socket
listener
=
new
Socket
(
AddressFamily
.
InterNetwork
,
SocketType
.
Stream
,
ProtocolType
.
Tcp
))
using
(
Socket
client
=
new
Socket
(
AddressFamily
.
InterNetwork
,
SocketType
.
Stream
,
ProtocolType
.
Tcp
))
{
listener
.
Bind
(
new
IPEndPoint
(
IPAddress
.
Loopback
,
0
));
listener
.
Listen
(
1
);
await
client
.
ConnectAsync
(
listener
.
LocalEndPoint
);
using
(
Socket
server
=
await
listener
.
AcceptAsync
())
{
WebSocket
websocket
=
CreateFromStream
(
new
NetworkStream
(
client
,
ownsSocket
:
false
),
isServer
:
false
,
null
,
Timeout
.
InfiniteTimeSpan
);
await
server
.
SendAsync
(
new
ArraySegment
<
byte
>(
new
byte
[
3
]
{
firstByte
,
secondByte
,
(
byte
)
'a'
}),
SocketFlags
.
None
);
var
buffer
=
new
byte
[
1
];
Task
<
WebSocketReceiveResult
>
t
=
websocket
.
ReceiveAsync
(
new
ArraySegment
<
byte
>(
buffer
),
CancellationToken
.
None
);
if
(
shouldFail
)
{
await
Assert
.
ThrowsAsync
<
WebSocketException
>(()
=>
t
);
Assert
.
Equal
(
WebSocketState
.
Aborted
,
websocket
.
State
);
}
else
{
WebSocketReceiveResult
result
=
await
t
;
Assert
.
True
(
result
.
EndOfMessage
);
Assert
.
Equal
(
1
,
result
.
Count
);
Assert
.
Equal
(
'a'
,
(
char
)
buffer
[
0
]);
}
}
}
}
[
Fact
]
public
async
Task
ReceiveAsync_ServerSplitHeader_ValidDataReceived
()
{
...
...
src/libraries/System.Net.WebSockets.WebSocketProtocol/src/Resources/Strings.resx
浏览文件 @
375a15ba
...
...
@@ -93,4 +93,22 @@
<data name="net_WebSockets_ArgumentOutOfRange_TooSmall" xml:space="preserve">
<value>The argument must be a value greater than {0}.</value>
</data>
<data name="net_Websockets_ReservedBitsSet" xml:space="preserve">
<value>The WebSocket received a frame with one or more reserved bits set.</value>
</data>
<data name="net_Websockets_ClientReceivedMaskedFrame" xml:space="preserve">
<value>The WebSocket server sent a masked frame.</value>
</data>
<data name="net_Websockets_ContinuationFromFinalFrame" xml:space="preserve">
<value>The WebSocket received a continuation frame from a previous final message.</value>
</data>
<data name="net_Websockets_NonContinuationAfterNonFinalFrame" xml:space="preserve">
<value>The WebSocket expected a continuation frame after having received a previous non-final frame.</value>
</data>
<data name="net_Websockets_InvalidControlMessage" xml:space="preserve">
<value>The WebSocket received an invalid control message.</value>
</data>
<data name="net_Websockets_UnknownOpcode" xml:space="preserve">
<value>The WebSocket received a frame with an unknown opcode: '0x{0}'.</value>
</data>
</root>
src/libraries/System.Net.WebSockets/src/Resources/Strings.resx
浏览文件 @
375a15ba
...
...
@@ -114,6 +114,24 @@
<data name="net_Websockets_AlreadyOneOutstandingOperation" xml:space="preserve">
<value>There is already one outstanding '{0}' call for this WebSocket instance. ReceiveAsync and SendAsync can be called simultaneously, but at most one outstanding operation for each of them is allowed at the same time.</value>
</data>
<data name="net_Websockets_ReservedBitsSet" xml:space="preserve">
<value>The WebSocket received a frame with one or more reserved bits set.</value>
</data>
<data name="net_Websockets_ClientReceivedMaskedFrame" xml:space="preserve">
<value>The WebSocket server sent a masked frame.</value>
</data>
<data name="net_Websockets_ContinuationFromFinalFrame" xml:space="preserve">
<value>The WebSocket received a continuation frame from a previous final message.</value>
</data>
<data name="net_Websockets_NonContinuationAfterNonFinalFrame" xml:space="preserve">
<value>The WebSocket expected a continuation frame after having received a previous non-final frame.</value>
</data>
<data name="net_Websockets_InvalidControlMessage" xml:space="preserve">
<value>The WebSocket received an invalid control message.</value>
</data>
<data name="net_Websockets_UnknownOpcode" xml:space="preserve">
<value>The WebSocket received a frame with an unknown opcode: '0x{0}'.</value>
</data>
<data name="NotReadableStream" xml:space="preserve">
<value>The base stream is not readable.</value>
</data>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录