copy.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  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.Read()
  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.Write(mb)
  25. if err != nil {
  26. for _, handler := range h.onWriteError {
  27. err = handler(err)
  28. }
  29. }
  30. return err
  31. }
  32. type CopyOption func(*copyHandler)
  33. func IgnoreReaderError() CopyOption {
  34. return func(handler *copyHandler) {
  35. handler.onReadError = append(handler.onReadError, func(err error) error {
  36. return nil
  37. })
  38. }
  39. }
  40. func IgnoreWriterError() CopyOption {
  41. return func(handler *copyHandler) {
  42. handler.onWriteError = append(handler.onWriteError, func(err error) error {
  43. return nil
  44. })
  45. }
  46. }
  47. func UpdateActivity(timer signal.ActivityUpdater) CopyOption {
  48. return func(handler *copyHandler) {
  49. handler.onData = append(handler.onData, func(MultiBuffer) {
  50. timer.Update()
  51. })
  52. }
  53. }
  54. func copyInternal(reader Reader, writer Writer, handler *copyHandler) error {
  55. for {
  56. buffer, err := handler.readFrom(reader)
  57. if err != nil {
  58. return err
  59. }
  60. if buffer.IsEmpty() {
  61. buffer.Release()
  62. continue
  63. }
  64. for _, handler := range handler.onData {
  65. handler(buffer)
  66. }
  67. if err := handler.writeTo(writer, buffer); err != nil {
  68. buffer.Release()
  69. return err
  70. }
  71. }
  72. }
  73. // Copy dumps all payload from reader to writer or stops when an error occurs.
  74. // ActivityTimer gets updated as soon as there is a payload.
  75. func Copy(reader Reader, writer Writer, options ...CopyOption) error {
  76. handler := new(copyHandler)
  77. for _, option := range options {
  78. option(handler)
  79. }
  80. err := copyInternal(reader, writer, handler)
  81. if err != nil && errors.Cause(err) != io.EOF {
  82. return err
  83. }
  84. return nil
  85. }