copy.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package buf
  2. import (
  3. "io"
  4. "v2ray.com/core/common/errors"
  5. "v2ray.com/core/common/signal"
  6. )
  7. type errorHandler func(error) error
  8. type dataHandler func(MultiBuffer)
  9. type copyHandler struct {
  10. onReadError []errorHandler
  11. onData []dataHandler
  12. onWriteError []errorHandler
  13. }
  14. func (h *copyHandler) readFrom(reader Reader) (MultiBuffer, error) {
  15. mb, err := reader.ReadMultiBuffer()
  16. if err != nil {
  17. for _, handler := range h.onReadError {
  18. err = handler(err)
  19. }
  20. }
  21. return mb, err
  22. }
  23. func (h *copyHandler) writeTo(writer Writer, mb MultiBuffer) error {
  24. err := writer.WriteMultiBuffer(mb)
  25. if err != nil {
  26. for _, handler := range h.onWriteError {
  27. err = handler(err)
  28. }
  29. }
  30. return err
  31. }
  32. type SizeCounter struct {
  33. Size int64
  34. }
  35. type CopyOption func(*copyHandler)
  36. func IgnoreReaderError() CopyOption {
  37. return func(handler *copyHandler) {
  38. handler.onReadError = append(handler.onReadError, func(err error) error {
  39. return nil
  40. })
  41. }
  42. }
  43. func IgnoreWriterError() CopyOption {
  44. return func(handler *copyHandler) {
  45. handler.onWriteError = append(handler.onWriteError, func(err error) error {
  46. return nil
  47. })
  48. }
  49. }
  50. func UpdateActivity(timer signal.ActivityUpdater) CopyOption {
  51. return func(handler *copyHandler) {
  52. handler.onData = append(handler.onData, func(MultiBuffer) {
  53. timer.Update()
  54. })
  55. }
  56. }
  57. func CountSize(sc *SizeCounter) CopyOption {
  58. return func(handler *copyHandler) {
  59. handler.onData = append(handler.onData, func(b MultiBuffer) {
  60. sc.Size += int64(b.Len())
  61. })
  62. }
  63. }
  64. func copyInternal(reader Reader, writer Writer, handler *copyHandler) error {
  65. for {
  66. buffer, err := handler.readFrom(reader)
  67. if err != nil {
  68. return err
  69. }
  70. if buffer.IsEmpty() {
  71. buffer.Release()
  72. continue
  73. }
  74. for _, handler := range handler.onData {
  75. handler(buffer)
  76. }
  77. if err := handler.writeTo(writer, buffer); err != nil {
  78. buffer.Release()
  79. return err
  80. }
  81. }
  82. }
  83. // Copy dumps all payload from reader to writer or stops when an error occurs.
  84. // ActivityTimer gets updated as soon as there is a payload.
  85. func Copy(reader Reader, writer Writer, options ...CopyOption) error {
  86. handler := new(copyHandler)
  87. for _, option := range options {
  88. option(handler)
  89. }
  90. err := copyInternal(reader, writer, handler)
  91. if err != nil && errors.Cause(err) != io.EOF {
  92. return err
  93. }
  94. return nil
  95. }