=htc fix WS masking for empty frames on client side
This commit is contained in:
parent
5e0caf8fe1
commit
4cbbb7dbad
2 changed files with 46 additions and 8 deletions
|
|
@ -51,12 +51,9 @@ private[http] object Masking {
|
|||
def onPush(part: FrameEvent, ctx: Context[FrameEvent]): SyncDirective =
|
||||
part match {
|
||||
case start @ FrameStart(header, data) ⇒
|
||||
if (header.length == 0) ctx.push(part)
|
||||
else {
|
||||
val mask = extractMask(header)
|
||||
become(new Running(mask))
|
||||
current.onPush(start.copy(header = setNewMask(header, mask)), ctx)
|
||||
}
|
||||
val mask = extractMask(header)
|
||||
become(new Running(mask))
|
||||
current.onPush(start.copy(header = setNewMask(header, mask)), ctx)
|
||||
case _: FrameData ⇒
|
||||
ctx.fail(new IllegalStateException("unexpected FrameData (need FrameStart first)"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,13 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
sub.expectNext(ByteString("def", "ASCII"))
|
||||
sub.expectComplete()
|
||||
}
|
||||
"unmask masked input on the server side for empty frame" in new ServerTestSetup {
|
||||
val mask = Random.nextInt()
|
||||
val header = frameHeader(Opcode.Binary, 0, fin = true, mask = Some(mask))
|
||||
|
||||
pushInput(header)
|
||||
expectBinaryMessage(BinaryMessage.Strict(ByteString.empty))
|
||||
}
|
||||
}
|
||||
"for text messages" - {
|
||||
"empty message" in new ClientTestSetup {
|
||||
|
|
@ -207,6 +214,13 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
sub.expectNext(ByteString("cdef€", "UTF-8"))
|
||||
sub.expectComplete()
|
||||
}
|
||||
"unmask masked input on the server side for empty frame" in new ServerTestSetup {
|
||||
val mask = Random.nextInt()
|
||||
val header = frameHeader(Opcode.Text, 0, fin = true, mask = Some(mask))
|
||||
|
||||
pushInput(header)
|
||||
expectTextMessage(TextMessage.Strict(""))
|
||||
}
|
||||
}
|
||||
}
|
||||
"render frames from messages" - {
|
||||
|
|
@ -265,6 +279,10 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
sub.sendComplete()
|
||||
expectFrameOnNetwork(Opcode.Continuation, ByteString.empty, fin = true)
|
||||
}
|
||||
"and mask input on the client side for empty frame" in new ClientTestSetup {
|
||||
pushMessage(BinaryMessage(ByteString.empty))
|
||||
expectMaskedFrameOnNetwork(Opcode.Binary, ByteString.empty, fin = true)
|
||||
}
|
||||
}
|
||||
"for text messages" - {
|
||||
"for a short strict message" in new ServerTestSetup {
|
||||
|
|
@ -347,6 +365,10 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
sub.sendComplete()
|
||||
expectFrameOnNetwork(Opcode.Continuation, ByteString.empty, fin = true)
|
||||
}
|
||||
"and mask input on the client side for empty frame" in new ClientTestSetup {
|
||||
pushMessage(TextMessage(""))
|
||||
expectMaskedFrameOnNetwork(Opcode.Text, ByteString.empty, fin = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
"supply automatic low-level websocket behavior" - {
|
||||
|
|
@ -440,7 +462,7 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
}
|
||||
"after receiving close frame without close code" in new ServerTestSetup {
|
||||
netInSub.expectRequest()
|
||||
pushInput(frameHeader(Opcode.Close, 0, fin = true))
|
||||
pushInput(frameHeader(Opcode.Close, 0, fin = true, mask = Some(Random.nextInt())))
|
||||
messageIn.expectComplete()
|
||||
|
||||
messageOutSub.sendComplete()
|
||||
|
|
@ -479,7 +501,7 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
netOutSub.request(10)
|
||||
messageInSub.request(10)
|
||||
|
||||
pushInput(frameHeader(Protocol.Opcode.Binary, 0, fin = false))
|
||||
pushInput(frameHeader(Protocol.Opcode.Binary, 0, fin = false, mask = Some(Random.nextInt())))
|
||||
val dataSource = expectBinaryMessage().dataStream
|
||||
val inSubscriber = TestSubscriber.manualProbe[ByteString]()
|
||||
dataSource.runWith(Sink(inSubscriber))
|
||||
|
|
@ -742,10 +764,23 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
pushInput(input)
|
||||
expectProtocolErrorOnNetwork()
|
||||
}
|
||||
"unmasked input on the server side for empty frame" in new ServerTestSetup {
|
||||
val input = frameHeader(Opcode.Binary, 0, fin = true)
|
||||
|
||||
pushInput(input)
|
||||
expectProtocolErrorOnNetwork()
|
||||
}
|
||||
"masked input on the client side" in new ClientTestSetup {
|
||||
val mask = Random.nextInt()
|
||||
val input = frameHeader(Opcode.Binary, 6, fin = true, mask = Some(mask)) ++ maskedASCII("abcdef", mask)._1
|
||||
|
||||
pushInput(input)
|
||||
expectProtocolErrorOnNetwork()
|
||||
}
|
||||
"masked input on the client side for empty frame" in new ClientTestSetup {
|
||||
val mask = Random.nextInt()
|
||||
val input = frameHeader(Opcode.Binary, 0, fin = true, mask = Some(mask))
|
||||
|
||||
pushInput(input)
|
||||
expectProtocolErrorOnNetwork()
|
||||
}
|
||||
|
|
@ -813,9 +848,15 @@ class MessageSpec extends FreeSpec with Matchers with WithMaterializerSpec {
|
|||
def expectBinaryMessage(): BinaryMessage =
|
||||
expectMessage().asInstanceOf[BinaryMessage]
|
||||
|
||||
def expectBinaryMessage(message: BinaryMessage): Unit =
|
||||
expectBinaryMessage() shouldEqual message
|
||||
|
||||
def expectTextMessage(): TextMessage =
|
||||
expectMessage().asInstanceOf[TextMessage]
|
||||
|
||||
def expectTextMessage(message: TextMessage): Unit =
|
||||
expectTextMessage() shouldEqual message
|
||||
|
||||
var inBuffer = ByteString.empty
|
||||
@tailrec final def expectNetworkData(bytes: Int): ByteString =
|
||||
if (inBuffer.size >= bytes) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue