2222import io .netty .util .IllegalReferenceCountException ;
2323import io .netty .util .ReferenceCountUtil ;
2424import io .netty .util .ReferenceCounted ;
25+ import io .netty .util .collection .IntObjectHashMap ;
26+ import io .netty .util .collection .IntObjectMap ;
2527import org .cloudburstmc .netty .channel .raknet .packet .EncapsulatedPacket ;
2628
2729import java .util .Objects ;
2830
2931public class SplitPacketHelper extends AbstractReferenceCounted {
30- private final EncapsulatedPacket [] packets ;
32+ private final IntObjectMap <EncapsulatedPacket > packets ;
33+ private final int expectedLength ;
3134 private final long created = System .currentTimeMillis ();
3235
3336 public SplitPacketHelper (long expectedLength ) {
3437 if (expectedLength < 2 ) {
3538 throw new IllegalArgumentException ("expectedLength must be greater than 1" );
3639 }
37- if (expectedLength > 8192 ) {
38- throw new IllegalArgumentException ("Too many split parts, expectedLength must be less than 8192" );
40+
41+ if (expectedLength > Integer .MAX_VALUE ) {
42+ throw new IllegalArgumentException ("expectedLength must be <= Integer.MAX_VALUE" );
3943 }
40- this .packets = new EncapsulatedPacket [(int ) expectedLength ];
44+
45+ this .expectedLength = (int ) expectedLength ;
46+ this .packets = new IntObjectHashMap <>();
4147 }
4248
43- public EncapsulatedPacket add (EncapsulatedPacket packet , ByteBufAllocator alloc ) {
49+ public EncapsulatedPacket add (EncapsulatedPacket packet , ByteBufAllocator alloc ) {
4450 Objects .requireNonNull (packet , "packet cannot be null" );
4551 if (!packet .isSplit ()) throw new IllegalArgumentException ("Packet is not split" );
4652 if (this .refCnt () <= 0 ) throw new IllegalReferenceCountException (this .refCnt ());
47- if (packet .getPartIndex () < 0 || packet .getPartIndex () >= this .packets .length ) {
53+
54+ int partIndex = packet .getPartIndex ();
55+ if (partIndex < 0 || partIndex >= this .expectedLength ) {
4856 throw new IllegalArgumentException (String .format ("Split packet part index out of range. Got %s, expected 0-%s" ,
49- packet . getPartIndex () , this .packets . length - 1 ));
57+ partIndex , this .expectedLength - 1 ));
5058 }
5159
52- int partIndex = packet .getPartIndex ();
53- if (this .packets [partIndex ] != null ) {
54- // Duplicate
60+ if (this .packets .containsKey (partIndex )) {
5561 return null ;
5662 }
63+
5764 // Retain the packet so it can be reassembled later.
58- this .packets [ partIndex ] = packet .retain ();
65+ this .packets . put ( partIndex , packet .retain () );
5966
60- int sz = 0 ;
61- for (EncapsulatedPacket netPacket : this .packets ) {
62- if (netPacket == null ) {
63- return null ;
67+ if (this .packets .size () == this .expectedLength ) {
68+ int sz = 0 ;
69+ // Iterate by index to ensure we sum sizes and write bytes in the correct order
70+ for (int i = 0 ; i < this .expectedLength ; i ++) {
71+ EncapsulatedPacket netPacket = this .packets .get (i );
72+ // netPacket should not be null here if size() == expectedLength and indices are verified
73+ sz += netPacket .getBuffer ().readableBytes ();
74+ }
75+
76+ // We can't use a composite buffer as the native code will choke on it
77+ ByteBuf reassembled = alloc .ioBuffer (sz );
78+ for (int i = 0 ; i < this .expectedLength ; i ++) {
79+ EncapsulatedPacket netPacket = this .packets .get (i );
80+ ByteBuf buf = netPacket .getBuffer ();
81+ reassembled .writeBytes (buf , buf .readerIndex (), buf .readableBytes ());
6482 }
65- sz += netPacket .getBuffer ().readableBytes ();
66- }
6783
68- // We can't use a composite buffer as the native code will choke on it
69- ByteBuf reassembled = alloc .ioBuffer (sz );
70- for (EncapsulatedPacket netPacket : this .packets ) {
71- ByteBuf buf = netPacket .getBuffer ();
72- reassembled .writeBytes (buf , buf .readerIndex (), buf .readableBytes ());
84+ return packet .fromSplit (reassembled );
7385 }
7486
75- return packet . fromSplit ( reassembled ) ;
87+ return null ;
7688 }
7789
7890 public boolean expired () {
@@ -82,11 +94,12 @@ public boolean expired() {
8294 return System .currentTimeMillis () - created >= 30000 ;
8395 }
8496
85- @ Override
97+ @ Override
8698 protected void deallocate () {
87- for (EncapsulatedPacket packet : this .packets ) {
99+ for (EncapsulatedPacket packet : this .packets . values () ) {
88100 ReferenceCountUtil .release (packet );
89101 }
102+ this .packets .clear ();
90103 }
91104
92105 @ Override
0 commit comments