@@ -91,7 +91,7 @@ module Reassembly_queue = struct
91
91
92
92
(* insert segment, potentially coalescing existing ones *)
93
93
let insert_seg t (seq , fin , data ) =
94
- (* they may overlap, the oldest seg wins *)
94
+ (* they may overlap, the newest seg wins *)
95
95
(* (1) figure out the place whereafter to insert the seg *)
96
96
(* (2) peek whether the next seg can be already coalesced *)
97
97
let inserted, segq =
@@ -123,39 +123,75 @@ module Reassembly_queue = struct
123
123
(* there are three cases:
124
124
- (a) the new seq is before the existing e.seq -> prepend
125
125
(and figure out whether to merge with e)
126
- seq < e.seq
126
+ seq <= e.seq
127
127
- (b) the new seq is within e.seq + len e -> append (partially)
128
128
seq <= e.seq + len
129
129
- (c) the new seq is way behind e.seq + len e -> move along
130
130
seq > e.seq + len
131
131
*)
132
- if Sequence. less seq e.seq then
132
+ if Sequence. less_equal seq e.seq then
133
133
(* case (a) *)
134
134
let seq_e = Sequence. addi seq (Cstruct. length data) in
135
- if Sequence. less_equal e.seq seq_e then
136
- (* we've to merge e into seq *)
137
- let skip_data = Sequence. sub seq_e e.seq in
138
- if Cstruct. length data > = skip_data then
139
- let data = Cstruct. shift data skip_data in
135
+ (* case (1): a new segment that is way before the existing one:
136
+ seq <= e.seq && seq_e <= e.seq -> e must be retained
137
+ case (2): a new segment that is partially before the existing:
138
+ seq <= e.seq && seq_e > e.seq -> e may be partially retained:
139
+ (i) seq_e >= e.seq_e -> drop e
140
+ (ii) seq_e < e.seq_e -> retain the last bytes of e
141
+ *)
142
+ if Sequence. less_equal seq_e e.seq then
143
+ if Sequence. equal seq_e e.seq then
140
144
let e = { seq ; fin = fin || e.fin ; data = e.data @ [ data ] } in
141
145
Some (e, Sequence. addi seq (Cstruct. lenv e.data)), e :: acc
142
146
else
143
- None , e :: acc
147
+ let e' = { seq ; fin ; data = [ data ] } in
148
+ Some (e', Sequence. addi seq (Cstruct. length data)), e :: e' :: acc
144
149
else
145
- let e' = { seq ; fin ; data = [ data ] } in
146
- Some (e', seq_e), e :: e' :: acc
150
+ let e_seq_e = Sequence. addi e.seq (Cstruct. lenv e.data) in
151
+ if Sequence. greater_equal seq_e e_seq_e then
152
+ let e' = { seq ; fin ; data = [ data ] } in
153
+ Some (e', seq_e), e' :: acc
154
+ else
155
+ (* we've to retain some parts of seq *)
156
+ let post =
157
+ let retain_data = Sequence. sub e_seq_e seq_e in
158
+ let skip_data = Cstruct. lenv e.data - retain_data in
159
+ Cstruct. shiftv (List. rev e.data) skip_data
160
+ in
161
+ let e = { seq ; fin = fin || e.fin ; data = List. rev (data :: post) } in
162
+ Some (e, Sequence. addi seq (Cstruct. lenv e.data)), e :: acc
147
163
else
148
- let e_end = Sequence. addi e.seq (Cstruct. lenv e.data) in
149
- if Sequence. less_equal seq e_end then
164
+ let e_seq_e = Sequence. addi e.seq (Cstruct. lenv e.data) in
165
+ if Sequence. less_equal seq e_seq_e then
150
166
(* case (b) we append to the thing *)
151
- let skip_data = Sequence. sub e_end seq in
152
- if Cstruct. length data > = skip_data then
153
- let data = Cstruct. shift data skip_data in
167
+ if Sequence. equal seq e_seq_e then
154
168
let e = { e with fin = fin || e.fin ; data = data :: e .data } in
155
- Some (e, Sequence. addi e_end (Cstruct. length data)), e :: acc
169
+ Some (e, Sequence. addi e_seq_e (Cstruct. length data)), e :: acc
156
170
else
157
- (* we just throw it away *)
158
- Some (e, e_end), e :: acc
171
+ let overlap = Sequence. sub e_seq_e seq in
172
+ let pre =
173
+ let rec cut_some amount = function
174
+ | [] -> []
175
+ | hd :: tl ->
176
+ if Cstruct. length hd < amount then
177
+ cut_some (amount - Cstruct. length hd) tl
178
+ else
179
+ Cstruct. sub hd amount (Cstruct. length hd - amount) :: tl
180
+ in
181
+ cut_some overlap e.data
182
+ in
183
+ let seq_e = Sequence. addi seq (Cstruct. length data) in
184
+ let end_ = Sequence. max e_seq_e seq_e in
185
+ let post =
186
+ if Sequence. greater e_seq_e seq_e then
187
+ let retain_data = Sequence. sub e_seq_e seq_e in
188
+ let skip_data = Cstruct. lenv e.data - retain_data in
189
+ Cstruct. shiftv (List. rev e.data) skip_data
190
+ else
191
+ []
192
+ in
193
+ let e = { e with fin = fin || e.fin ; data = post @ data :: pre } in
194
+ Some (e, end_), e :: acc
159
195
else
160
196
(None , e :: acc))
161
197
(None , [] ) t
0 commit comments