15
15
*/
16
16
package io.rsocket.android
17
17
18
- import io.rsocket.android.frame.FrameHeaderFlyweight.FLAGS_M
19
-
20
- import io.netty.buffer.*
18
+ import com.sun.org.apache.xpath.internal.operations.Bool
19
+ import io.netty.buffer.ByteBuf
20
+ import io.netty.buffer.ByteBufAllocator
21
+ import io.netty.buffer.ByteBufHolder
22
+ import io.netty.buffer.Unpooled
21
23
import io.netty.util.IllegalReferenceCountException
22
24
import io.netty.util.Recycler
23
25
import io.netty.util.Recycler.Handle
24
26
import io.netty.util.ResourceLeakDetector
25
- import io.rsocket.android.frame.ErrorFrameFlyweight
26
- import io.rsocket.android.frame.FrameHeaderFlyweight
27
- import io.rsocket.android.frame.KeepaliveFrameFlyweight
28
- import io.rsocket.android.frame.LeaseFrameFlyweight
29
- import io.rsocket.android.frame.RequestFrameFlyweight
30
- import io.rsocket.android.frame.RequestNFrameFlyweight
31
- import io.rsocket.android.frame.SetupFrameFlyweight
32
- import io.rsocket.android.frame.VersionFlyweight
27
+ import io.rsocket.android.frame.*
28
+ import io.rsocket.android.frame.FrameHeaderFlyweight.FLAGS_M
29
+ import org.slf4j.LoggerFactory
33
30
import java.nio.ByteBuffer
34
31
import java.nio.charset.StandardCharsets
35
- import org.slf4j.LoggerFactory
36
32
37
33
/* *
38
34
* Represents a Frame sent over a [DuplexConnection].
@@ -51,10 +47,12 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
51
47
52
48
/* * Return the content which is held by this [Frame]. */
53
49
override fun content (): ByteBuf {
54
- if (content!! .refCnt() <= 0 ) {
55
- throw IllegalReferenceCountException (content!! .refCnt())
56
- }
57
- return content as ByteBuf
50
+ val c = content
51
+ return if (c == null ) {
52
+ throw IllegalReferenceCountException (0 )
53
+ } else if (c.refCnt() <= 0 ) {
54
+ throw IllegalReferenceCountException (c.refCnt())
55
+ } else content as ByteBuf
58
56
}
59
57
60
58
/* * Creates a deep copy of this [Frame]. */
@@ -79,7 +77,7 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
79
77
* Returns the reference count of this object. If `0`, it means this object has been
80
78
* deallocated.
81
79
*/
82
- override fun refCnt (): Int = content!! .refCnt()
80
+ override fun refCnt (): Int = content? .refCnt() ? : 0
83
81
84
82
/* * Increases the reference count by `1`. */
85
83
override fun retain (): Frame {
@@ -210,11 +208,17 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
210
208
*/
211
209
fun flags (): Int = FrameHeaderFlyweight .flags(content!! )
212
210
213
- fun hasMetadata (): Boolean = isFlagSet(this .flags(), FLAGS_M )
211
+ fun isFlagSet (flag : Int ): Boolean {
212
+ return isFlagSet(this .flags(), flag)
213
+ }
214
+
215
+ fun hasMetadata (): Boolean = isFlagSet(FLAGS_M )
214
216
215
217
val dataUtf8: String
216
218
get() = StandardCharsets .UTF_8 .decode(data).toString()
217
219
220
+ val isFragmentable: Boolean
221
+ get() = type.isFragmentable
218
222
/* TODO:
219
223
*
220
224
* fromRequest(type, id, payload)
@@ -227,6 +231,7 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
227
231
228
232
fun from (
229
233
flags : Int ,
234
+ version : Int ,
230
235
keepaliveInterval : Int ,
231
236
maxLifetime : Int ,
232
237
metadataMimeType : String ,
@@ -250,6 +255,7 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
250
255
SetupFrameFlyweight .encode(
251
256
frame.content!! ,
252
257
flags,
258
+ version,
253
259
keepaliveInterval,
254
260
maxLifetime,
255
261
metadataMimeType,
@@ -259,6 +265,25 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
259
265
return frame
260
266
}
261
267
268
+ fun from (
269
+ flags : Int ,
270
+ keepaliveInterval : Int ,
271
+ maxLifetime : Int ,
272
+ metadataMimeType : String ,
273
+ dataMimeType : String ,
274
+ payload : Payload ): Frame {
275
+
276
+ return from(
277
+ flags,
278
+ SetupFrameFlyweight .CURRENT_VERSION ,
279
+ keepaliveInterval,
280
+ maxLifetime,
281
+ metadataMimeType,
282
+ dataMimeType,
283
+ payload)
284
+ }
285
+
286
+
262
287
fun getFlags (frame : Frame ): Int {
263
288
ensureFrameType(FrameType .SETUP , frame)
264
289
val flags = FrameHeaderFlyweight .flags(frame.content!! )
@@ -271,6 +296,20 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
271
296
return SetupFrameFlyweight .version(frame.content!! )
272
297
}
273
298
299
+ fun resumeEnabled (frame : Frame ): Boolean {
300
+ ensureFrameType(FrameType .SETUP , frame)
301
+ return Frame .isFlagSet(
302
+ frame.flags(),
303
+ SetupFrameFlyweight .FLAGS_RESUME_ENABLE )
304
+ }
305
+
306
+ fun leaseEnabled (frame : Frame ): Boolean {
307
+ ensureFrameType(FrameType .SETUP , frame)
308
+ return Frame .isFlagSet(
309
+ frame.flags(),
310
+ SetupFrameFlyweight .FLAGS_WILL_HONOR_LEASE )
311
+ }
312
+
274
313
fun keepaliveInterval (frame : Frame ): Int {
275
314
ensureFrameType(FrameType .SETUP , frame)
276
315
return SetupFrameFlyweight .keepaliveInterval(frame.content!! )
@@ -429,14 +468,14 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
429
468
fun from (
430
469
streamId : Int ,
431
470
type : FrameType ,
432
- metadata : ByteBuf ,
471
+ metadata : ByteBuf ? ,
433
472
data : ByteBuf ,
434
473
initialRequestN : Int ,
435
474
flags : Int ): Frame {
436
475
val frame = RECYCLER .get()
437
476
frame.content = ByteBufAllocator .DEFAULT .buffer(
438
477
RequestFrameFlyweight .computeFrameLength(
439
- type, metadata.readableBytes(), data.readableBytes()))
478
+ type, metadata? .readableBytes(), data.readableBytes()))
440
479
frame.content!! .writerIndex(
441
480
RequestFrameFlyweight .encode(
442
481
frame.content!! ,
@@ -449,6 +488,21 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
449
488
return frame
450
489
}
451
490
491
+ fun from (streamId : Int ,
492
+ type : FrameType ,
493
+ metadata : ByteBuf ? ,
494
+ data : ByteBuf ,
495
+ flags : Int ): Frame {
496
+
497
+ return PayloadFrame .from(
498
+ streamId,
499
+ type,
500
+ metadata,
501
+ data,
502
+ flags)
503
+ }
504
+
505
+
452
506
fun initialRequestN (frame : Frame ): Int {
453
507
val type = frame.type
454
508
if (! type.isRequestType) {
@@ -538,6 +592,66 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
538
592
}
539
593
}
540
594
595
+ object Fragmentation {
596
+
597
+ fun assembleFrame (blueprintFrame : Frame ,
598
+ metadata : ByteBuf ,
599
+ data : ByteBuf ): Frame =
600
+
601
+ create(blueprintFrame,
602
+ metadata,
603
+ data,
604
+ { it and FrameHeaderFlyweight .FLAGS_F .inv () })
605
+
606
+ fun sliceFrame (blueprintFrame : Frame ,
607
+ metadata : ByteBuf ? ,
608
+ data : ByteBuf ,
609
+ additionalFlags : Int ): Frame =
610
+
611
+ create(blueprintFrame,
612
+ metadata,
613
+ data,
614
+ { it or additionalFlags })
615
+
616
+ private inline fun create (blueprintFrame : Frame ,
617
+ metadata : ByteBuf ? ,
618
+ data : ByteBuf ,
619
+ modifyFlags : (Int ) -> Int ): Frame =
620
+ when (blueprintFrame.type) {
621
+ FrameType .FIRE_AND_FORGET ,
622
+ FrameType .REQUEST_RESPONSE -> {
623
+ Frame .Request .from(
624
+ blueprintFrame.streamId,
625
+ blueprintFrame.type,
626
+ metadata,
627
+ data,
628
+ modifyFlags(blueprintFrame.flags()))
629
+ }
630
+ FrameType .NEXT ,
631
+ FrameType .NEXT_COMPLETE -> {
632
+ Frame .PayloadFrame .from(
633
+ blueprintFrame.streamId,
634
+ blueprintFrame.type,
635
+ metadata,
636
+ data,
637
+ modifyFlags(blueprintFrame.flags()))
638
+ }
639
+
640
+ FrameType .REQUEST_STREAM ,
641
+ FrameType .REQUEST_CHANNEL -> {
642
+ Frame .Request .from(
643
+ blueprintFrame.streamId,
644
+ blueprintFrame.type,
645
+ metadata,
646
+ data,
647
+ Frame .Request .initialRequestN(blueprintFrame),
648
+ modifyFlags(blueprintFrame.flags()))
649
+ }
650
+ else -> throw AssertionError (" Non-fragmentable frame: " +
651
+ " ${blueprintFrame.type} " )
652
+ }
653
+ }
654
+
541
655
override fun toString (): String {
542
656
val type = FrameHeaderFlyweight .frameType(content!! )
543
657
val payload = StringBuilder ()
@@ -587,7 +701,7 @@ class Frame private constructor(private val handle: Handle<Frame>) : ByteBufHold
587
701
}
588
702
589
703
companion object {
590
- val NULL_BYTEBUFFER : ByteBuffer = ByteBuffer .allocateDirect(0 )
704
+ val NULL_BYTEBUFFER : ByteBuffer = ByteBuffer .allocateDirect(0 )
591
705
592
706
private val RECYCLER = object : Recycler <Frame >() {
593
707
override fun newObject (handle : Handle <Frame >): Frame {
0 commit comments