github.com/sagernet/gvisor@v0.0.0-20240428053021-e691de28565f/pkg/buffer/buffer.go (about) 1 // Copyright 2022 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package buffer provides the implementation of a non-contiguous buffer that 16 // is reference counted, pooled, and copy-on-write. It allows O(1) append, 17 // and prepend operations. 18 package buffer 19 20 import ( 21 "fmt" 22 "github.com/sagernet/sing/common" 23 "io" 24 25 "github.com/sagernet/gvisor/pkg/tcpip/checksum" 26 ) 27 28 // Buffer is a non-linear buffer. 29 // 30 // +stateify savable 31 type Buffer struct { 32 data ViewList `state:".([]byte)"` 33 size int64 34 } 35 36 func (b *Buffer) removeView(v *View) { 37 b.data.Remove(v) 38 v.Release() 39 } 40 41 // MakeWithData creates a new Buffer initialized with given data. This function 42 // should be used with caution to avoid unnecessary []byte allocations. When in 43 // doubt use NewWithView to maximize chunk reuse. 44 func MakeWithData(b []byte) Buffer { 45 buf := Buffer{} 46 if len(b) == 0 { 47 return buf 48 } 49 v := NewViewWithData(b) 50 buf.Append(v) 51 return buf 52 } 53 54 // MakeWithView creates a new Buffer initialized with given view. This function 55 // takes ownership of v. 56 func MakeWithView(v *View) Buffer { 57 if v == nil { 58 return Buffer{} 59 } 60 b := Buffer{ 61 size: int64(v.Size()), 62 } 63 if b.size == 0 { 64 v.Release() 65 return b 66 } 67 b.data.PushBack(v) 68 return b 69 } 70 71 // Release frees all resources held by b. 72 func (b *Buffer) Release() { 73 for v := b.data.Front(); v != nil; v = b.data.Front() { 74 b.removeView(v) 75 } 76 b.size = 0 77 } 78 79 // TrimFront removes the first count bytes from the buffer. 80 func (b *Buffer) TrimFront(count int64) { 81 if count >= b.size { 82 b.advanceRead(b.size) 83 } else { 84 b.advanceRead(count) 85 } 86 } 87 88 // ReadAt implements io.ReaderAt.ReadAt. 89 func (b *Buffer) ReadAt(p []byte, offset int64) (int, error) { 90 var ( 91 skipped int64 92 done int64 93 ) 94 for v := b.data.Front(); v != nil && done < int64(len(p)); v = v.Next() { 95 needToSkip := int(offset - skipped) 96 if sz := v.Size(); sz <= needToSkip { 97 skipped += int64(sz) 98 continue 99 } 100 101 // Actually read data. 102 n := copy(p[done:], v.AsSlice()[needToSkip:]) 103 skipped += int64(needToSkip) 104 done += int64(n) 105 } 106 if int(done) < len(p) || offset+done == b.size { 107 return int(done), io.EOF 108 } 109 return int(done), nil 110 } 111 112 // advanceRead advances the Buffer's read index. 113 // 114 // Precondition: there must be sufficient bytes in the buffer. 115 func (b *Buffer) advanceRead(count int64) { 116 for v := b.data.Front(); v != nil && count > 0; { 117 sz := int64(v.Size()) 118 if sz > count { 119 // There is still data for reading. 120 v.TrimFront(int(count)) 121 b.size -= count 122 count = 0 123 return 124 } 125 126 // Consume the whole view. 127 oldView := v 128 v = v.Next() // Iterate. 129 b.removeView(oldView) 130 131 // Update counts. 132 count -= sz 133 b.size -= sz 134 } 135 if count > 0 { 136 panic(fmt.Sprintf("advanceRead still has %d bytes remaining", count)) 137 } 138 } 139 140 // Truncate truncates the Buffer to the given length. 141 // 142 // This will not grow the Buffer, only shrink it. If a length is passed that is 143 // greater than the current size of the Buffer, then nothing will happen. 144 // 145 // Precondition: length must be >= 0. 146 func (b *Buffer) Truncate(length int64) { 147 if length < 0 { 148 panic("negative length provided") 149 } 150 if length >= b.size { 151 return // Nothing to do. 152 } 153 for v := b.data.Back(); v != nil && b.size > length; v = b.data.Back() { 154 sz := int64(v.Size()) 155 if after := b.size - sz; after < length { 156 // Truncate the buffer locally. 157 left := (length - after) 158 v.write = v.read + int(left) 159 b.size = length 160 break 161 } 162 163 // Drop the buffer completely; see above. 164 b.removeView(v) 165 b.size -= sz 166 } 167 } 168 169 // GrowTo grows the given Buffer to the number of bytes, which will be appended. 170 // If zero is true, all these bytes will be zero. If zero is false, then this is 171 // the caller's responsibility. 172 // 173 // Precondition: length must be >= 0. 174 func (b *Buffer) GrowTo(length int64, zero bool) { 175 if length < 0 { 176 panic("negative length provided") 177 } 178 for b.size < length { 179 v := b.data.Back() 180 181 // Is there some space in the last buffer? 182 if v.Full() { 183 v = NewView(int(length - b.size)) 184 b.data.PushBack(v) 185 } 186 187 // Write up to length bytes. 188 sz := v.AvailableSize() 189 if int64(sz) > length-b.size { 190 sz = int(length - b.size) 191 } 192 193 // Zero the written section. 194 if zero { 195 common.ClearArray(v.chunk.data[v.write : v.write+sz]) 196 } 197 198 // Advance the index. 199 v.Grow(sz) 200 b.size += int64(sz) 201 } 202 } 203 204 // Prepend prepends the given data. Prepend takes ownership of src. 205 func (b *Buffer) Prepend(src *View) error { 206 if src == nil { 207 return nil 208 } 209 if src.Size() == 0 { 210 src.Release() 211 return nil 212 } 213 // If the first buffer does not have room just prepend the view. 214 v := b.data.Front() 215 if v == nil || v.read == 0 { 216 b.prependOwned(src) 217 return nil 218 } 219 220 // If there's room at the front and we won't incur a copy by writing to this 221 // view, fill in the extra room first. 222 if !v.sharesChunk() { 223 avail := v.read 224 vStart := 0 225 srcStart := src.Size() - avail 226 if avail > src.Size() { 227 vStart = avail - src.Size() 228 srcStart = 0 229 } 230 // Save the write index and restore it after. 231 old := v.write 232 v.read = vStart 233 n, err := v.WriteAt(src.AsSlice()[srcStart:], 0) 234 if err != nil { 235 return fmt.Errorf("could not write to view during append: %w", err) 236 } 237 b.size += int64(n) 238 v.write = old 239 src.write = srcStart 240 241 // If there's no more to be written, then we're done. 242 if src.Size() == 0 { 243 src.Release() 244 return nil 245 } 246 } 247 248 // Otherwise, just prepend the view. 249 b.prependOwned(src) 250 return nil 251 } 252 253 // Append appends the given data. Append takes ownership of src. 254 func (b *Buffer) Append(src *View) error { 255 if src == nil { 256 return nil 257 } 258 if src.Size() == 0 { 259 src.Release() 260 return nil 261 } 262 // If the last buffer is full, just append the view. 263 v := b.data.Back() 264 if v.Full() { 265 b.appendOwned(src) 266 return nil 267 } 268 269 // If a write won't incur a copy, then fill the back of the existing last 270 // chunk. 271 if !v.sharesChunk() { 272 writeSz := src.Size() 273 if src.Size() > v.AvailableSize() { 274 writeSz = v.AvailableSize() 275 } 276 done, err := v.Write(src.AsSlice()[:writeSz]) 277 if err != nil { 278 return fmt.Errorf("could not write to view during append: %w", err) 279 } 280 src.TrimFront(done) 281 b.size += int64(done) 282 if src.Size() == 0 { 283 src.Release() 284 return nil 285 } 286 } 287 288 // If there is still data left just append the src. 289 b.appendOwned(src) 290 return nil 291 } 292 293 func (b *Buffer) appendOwned(v *View) { 294 b.data.PushBack(v) 295 b.size += int64(v.Size()) 296 } 297 298 func (b *Buffer) prependOwned(v *View) { 299 b.data.PushFront(v) 300 b.size += int64(v.Size()) 301 } 302 303 // PullUp makes the specified range contiguous and returns the backing memory. 304 func (b *Buffer) PullUp(offset, length int) (View, bool) { 305 if length == 0 { 306 return View{}, true 307 } 308 tgt := Range{begin: offset, end: offset + length} 309 if tgt.Intersect(Range{end: int(b.size)}).Len() != length { 310 return View{}, false 311 } 312 313 curr := Range{} 314 v := b.data.Front() 315 for ; v != nil; v = v.Next() { 316 origLen := v.Size() 317 curr.end = curr.begin + origLen 318 319 if x := curr.Intersect(tgt); x.Len() == tgt.Len() { 320 // buf covers the whole requested target range. 321 sub := x.Offset(-curr.begin) 322 // Don't increment the reference count of the underlying chunk. Views 323 // returned by PullUp are explicitly unowned and read only 324 new := View{ 325 read: v.read + sub.begin, 326 write: v.read + sub.end, 327 chunk: v.chunk, 328 } 329 return new, true 330 } else if x.Len() > 0 { 331 // buf is pointing at the starting buffer we want to merge. 332 break 333 } 334 335 curr.begin += origLen 336 } 337 338 // Calculate the total merged length. 339 totLen := 0 340 for n := v; n != nil; n = n.Next() { 341 totLen += n.Size() 342 if curr.begin+totLen >= tgt.end { 343 break 344 } 345 } 346 347 // Merge the buffers. 348 merged := NewViewSize(totLen) 349 off := 0 350 for n := v; n != nil && off < totLen; { 351 merged.WriteAt(n.AsSlice(), off) 352 off += n.Size() 353 354 // Remove buffers except for the first one, which will be reused. 355 if n == v { 356 n = n.Next() 357 } else { 358 old := n 359 n = n.Next() 360 b.removeView(old) 361 } 362 } 363 // Make data the first buffer. 364 b.data.InsertBefore(v, merged) 365 b.removeView(v) 366 367 r := tgt.Offset(-curr.begin) 368 pulled := View{ 369 read: r.begin, 370 write: r.end, 371 chunk: merged.chunk, 372 } 373 return pulled, true 374 } 375 376 // Flatten returns a flattened copy of this data. 377 // 378 // This method should not be used in any performance-sensitive paths. It may 379 // allocate a fresh byte slice sufficiently large to contain all the data in 380 // the buffer. This is principally for debugging. 381 // 382 // N.B. Tee data still belongs to this Buffer, as if there is a single buffer 383 // present, then it will be returned directly. This should be used for 384 // temporary use only, and a reference to the given slice should not be held. 385 func (b *Buffer) Flatten() []byte { 386 if v := b.data.Front(); v == nil { 387 return nil // No data at all. 388 } 389 data := make([]byte, 0, b.size) // Need to flatten. 390 for v := b.data.Front(); v != nil; v = v.Next() { 391 // Copy to the allocated slice. 392 data = append(data, v.AsSlice()...) 393 } 394 return data 395 } 396 397 // Size indicates the total amount of data available in this Buffer. 398 func (b *Buffer) Size() int64 { 399 return b.size 400 } 401 402 // AsViewList returns the ViewList backing b. Users may not save or modify the 403 // ViewList returned. 404 func (b *Buffer) AsViewList() ViewList { 405 return b.data 406 } 407 408 // Clone creates a copy-on-write clone of b. The underlying chunks are shared 409 // until they are written to. 410 func (b *Buffer) Clone() Buffer { 411 other := Buffer{ 412 size: b.size, 413 } 414 for v := b.data.Front(); v != nil; v = v.Next() { 415 newView := v.Clone() 416 other.data.PushBack(newView) 417 } 418 return other 419 } 420 421 // DeepClone creates a deep clone of b, copying data such that no bytes are 422 // shared with any other Buffers. 423 func (b *Buffer) DeepClone() Buffer { 424 newBuf := Buffer{} 425 buf := b.Clone() 426 reader := buf.AsBufferReader() 427 newBuf.WriteFromReader(&reader, b.size) 428 return newBuf 429 } 430 431 // Apply applies the given function across all valid data. 432 func (b *Buffer) Apply(fn func(*View)) { 433 for v := b.data.Front(); v != nil; v = v.Next() { 434 d := v.Clone() 435 fn(d) 436 d.Release() 437 } 438 } 439 440 // SubApply applies fn to a given range of data in b. Any part of the range 441 // outside of b is ignored. 442 func (b *Buffer) SubApply(offset, length int, fn func(*View)) { 443 for v := b.data.Front(); length > 0 && v != nil; v = v.Next() { 444 if offset >= v.Size() { 445 offset -= v.Size() 446 continue 447 } 448 d := v.Clone() 449 if offset > 0 { 450 d.TrimFront(offset) 451 offset = 0 452 } 453 if length < d.Size() { 454 d.write = d.read + length 455 } 456 fn(d) 457 length -= d.Size() 458 d.Release() 459 } 460 } 461 462 // Checksum calculates a checksum over the buffer's payload starting at offset. 463 func (b *Buffer) Checksum(offset int) uint16 { 464 if offset >= int(b.size) { 465 return 0 466 } 467 var v *View 468 for v = b.data.Front(); v != nil && offset >= v.Size(); v = v.Next() { 469 offset -= v.Size() 470 } 471 472 var cs checksum.Checksumer 473 cs.Add(v.AsSlice()[offset:]) 474 for v = v.Next(); v != nil; v = v.Next() { 475 cs.Add(v.AsSlice()) 476 } 477 return cs.Checksum() 478 } 479 480 // Merge merges the provided Buffer with this one. 481 // 482 // The other Buffer will be appended to v, and other will be empty after this 483 // operation completes. 484 func (b *Buffer) Merge(other *Buffer) { 485 b.data.PushBackList(&other.data) 486 other.data = ViewList{} 487 488 // Adjust sizes. 489 b.size += other.size 490 other.size = 0 491 } 492 493 // WriteFromReader writes to the buffer from an io.Reader. A maximum read size 494 // of MaxChunkSize is enforced to prevent allocating views from the heap. 495 func (b *Buffer) WriteFromReader(r io.Reader, count int64) (int64, error) { 496 return b.WriteFromReaderAndLimitedReader(r, count, nil) 497 } 498 499 // WriteFromReaderAndLimitedReader is the same as WriteFromReader, but 500 // optimized to avoid allocations if a LimitedReader is passed in. 501 // 502 // This function clobbers the values of lr. 503 func (b *Buffer) WriteFromReaderAndLimitedReader(r io.Reader, count int64, lr *io.LimitedReader) (int64, error) { 504 if lr == nil { 505 lr = &io.LimitedReader{} 506 } 507 508 var done int64 509 for done < count { 510 vsize := count - done 511 if vsize > MaxChunkSize { 512 vsize = MaxChunkSize 513 } 514 v := NewView(int(vsize)) 515 lr.R = r 516 lr.N = vsize 517 n, err := io.Copy(v, lr) 518 b.Append(v) 519 done += n 520 if err == io.EOF { 521 break 522 } 523 if err != nil { 524 return done, err 525 } 526 } 527 return done, nil 528 } 529 530 // ReadToWriter reads from the buffer into an io.Writer. 531 // 532 // N.B. This does not consume the bytes read. TrimFront should 533 // be called appropriately after this call in order to do so. 534 func (b *Buffer) ReadToWriter(w io.Writer, count int64) (int64, error) { 535 bytesLeft := int(count) 536 for v := b.data.Front(); v != nil && bytesLeft > 0; v = v.Next() { 537 view := v.Clone() 538 if view.Size() > bytesLeft { 539 view.CapLength(bytesLeft) 540 } 541 n, err := io.Copy(w, view) 542 bytesLeft -= int(n) 543 view.Release() 544 if err != nil { 545 return count - int64(bytesLeft), err 546 } 547 } 548 return count - int64(bytesLeft), nil 549 } 550 551 // read implements the io.Reader interface. This method is used by BufferReader 552 // to consume its underlying buffer. To perform io operations on buffers 553 // directly, use ReadToWriter or WriteToReader. 554 func (b *Buffer) read(p []byte) (int, error) { 555 if len(p) == 0 { 556 return 0, nil 557 } 558 if b.Size() == 0 { 559 return 0, io.EOF 560 } 561 done := 0 562 v := b.data.Front() 563 for v != nil && done < len(p) { 564 n, err := v.Read(p[done:]) 565 done += n 566 next := v.Next() 567 if v.Size() == 0 { 568 b.removeView(v) 569 } 570 b.size -= int64(n) 571 if err != nil && err != io.EOF { 572 return done, err 573 } 574 v = next 575 } 576 return done, nil 577 } 578 579 // readByte implements the io.ByteReader interface. This method is used by 580 // BufferReader to consume its underlying buffer. To perform io operations on 581 // buffers directly, use ReadToWriter or WriteToReader. 582 func (b *Buffer) readByte() (byte, error) { 583 if b.Size() == 0 { 584 return 0, io.EOF 585 } 586 v := b.data.Front() 587 bt := v.AsSlice()[0] 588 b.TrimFront(1) 589 return bt, nil 590 } 591 592 // AsBufferReader returns the Buffer as a BufferReader capable of io methods. 593 // The new BufferReader takes ownership of b. 594 func (b *Buffer) AsBufferReader() BufferReader { 595 return BufferReader{b} 596 } 597 598 // BufferReader implements io methods on Buffer. Users must call Close() 599 // when finished with the buffer to free the underlying memory. 600 type BufferReader struct { 601 b *Buffer 602 } 603 604 // Read implements the io.Reader interface. 605 func (br *BufferReader) Read(p []byte) (int, error) { 606 return br.b.read(p) 607 } 608 609 // ReadByte implements the io.ByteReader interface. 610 func (br *BufferReader) ReadByte() (byte, error) { 611 return br.b.readByte() 612 } 613 614 // Close implements the io.Closer interface. 615 func (br *BufferReader) Close() { 616 br.b.Release() 617 } 618 619 // Len returns the number of bytes in the unread portion of the buffer. 620 func (br *BufferReader) Len() int { 621 return int(br.b.Size()) 622 } 623 624 // Range specifies a range of buffer. 625 type Range struct { 626 begin int 627 end int 628 } 629 630 // Intersect returns the intersection of x and y. 631 func (x Range) Intersect(y Range) Range { 632 if x.begin < y.begin { 633 x.begin = y.begin 634 } 635 if x.end > y.end { 636 x.end = y.end 637 } 638 if x.begin >= x.end { 639 return Range{} 640 } 641 return x 642 } 643 644 // Offset returns x offset by off. 645 func (x Range) Offset(off int) Range { 646 x.begin += off 647 x.end += off 648 return x 649 } 650 651 // Len returns the length of x. 652 func (x Range) Len() int { 653 l := x.end - x.begin 654 if l < 0 { 655 l = 0 656 } 657 return l 658 }