timed_io.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package net
  2. import (
  3. "io"
  4. "net"
  5. "time"
  6. "v2ray.com/core/common"
  7. )
  8. var (
  9. emptyTime time.Time
  10. )
  11. type TimeOutReader struct {
  12. timeout uint32
  13. connection net.Conn
  14. worker io.Reader
  15. }
  16. func NewTimeOutReader(timeout uint32 /* seconds */, connection net.Conn) *TimeOutReader {
  17. reader := &TimeOutReader{
  18. connection: connection,
  19. timeout: 0,
  20. }
  21. reader.SetTimeOut(timeout)
  22. return reader
  23. }
  24. func (reader *TimeOutReader) Read(p []byte) (int, error) {
  25. return reader.worker.Read(p)
  26. }
  27. func (reader *TimeOutReader) GetTimeOut() uint32 {
  28. return reader.timeout
  29. }
  30. func (reader *TimeOutReader) SetTimeOut(value uint32) {
  31. if reader.worker != nil && value == reader.timeout {
  32. return
  33. }
  34. reader.timeout = value
  35. if value > 0 {
  36. reader.worker = &timedReaderWorker{
  37. timeout: value,
  38. connection: reader.connection,
  39. }
  40. } else {
  41. reader.worker = &noOpReaderWorker{
  42. connection: reader.connection,
  43. }
  44. }
  45. }
  46. func (reader *TimeOutReader) Release() {
  47. common.Release(reader.connection)
  48. common.Release(reader.worker)
  49. }
  50. type timedReaderWorker struct {
  51. timeout uint32
  52. connection net.Conn
  53. }
  54. func (v *timedReaderWorker) Read(p []byte) (int, error) {
  55. deadline := time.Duration(v.timeout) * time.Second
  56. v.connection.SetReadDeadline(time.Now().Add(deadline))
  57. nBytes, err := v.connection.Read(p)
  58. v.connection.SetReadDeadline(emptyTime)
  59. return nBytes, err
  60. }
  61. type noOpReaderWorker struct {
  62. connection net.Conn
  63. }
  64. func (v *noOpReaderWorker) Read(p []byte) (int, error) {
  65. return v.connection.Read(p)
  66. }