freedom.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package freedom
  2. import (
  3. "net"
  4. "sync"
  5. v2io "github.com/v2ray/v2ray-core/common/io"
  6. "github.com/v2ray/v2ray-core/common/log"
  7. v2net "github.com/v2ray/v2ray-core/common/net"
  8. "github.com/v2ray/v2ray-core/common/retry"
  9. "github.com/v2ray/v2ray-core/transport/dialer"
  10. "github.com/v2ray/v2ray-core/transport/ray"
  11. )
  12. type FreedomConnection struct {
  13. }
  14. func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
  15. log.Info("Freedom: Opening connection to ", firstPacket.Destination())
  16. var conn net.Conn
  17. err := retry.Timed(5, 100).On(func() error {
  18. rawConn, err := dialer.Dial(firstPacket.Destination())
  19. if err != nil {
  20. return err
  21. }
  22. conn = rawConn
  23. return nil
  24. })
  25. if err != nil {
  26. close(ray.OutboundOutput())
  27. log.Error("Freedom: Failed to open connection to ", firstPacket.Destination(), ": ", err)
  28. return err
  29. }
  30. defer conn.Close()
  31. input := ray.OutboundInput()
  32. output := ray.OutboundOutput()
  33. var readMutex, writeMutex sync.Mutex
  34. readMutex.Lock()
  35. writeMutex.Lock()
  36. if chunk := firstPacket.Chunk(); chunk != nil {
  37. conn.Write(chunk.Value)
  38. chunk.Release()
  39. }
  40. if !firstPacket.MoreChunks() {
  41. writeMutex.Unlock()
  42. } else {
  43. go func() {
  44. v2io.ChanToWriter(conn, input)
  45. writeMutex.Unlock()
  46. }()
  47. }
  48. go func() {
  49. defer readMutex.Unlock()
  50. defer close(output)
  51. response, err := v2io.ReadFrom(conn, nil)
  52. log.Info("Freedom receives ", response.Len(), " bytes from ", conn.RemoteAddr())
  53. if response.Len() > 0 {
  54. output <- response
  55. } else {
  56. response.Release()
  57. }
  58. if err != nil {
  59. return
  60. }
  61. if firstPacket.Destination().IsUDP() {
  62. return
  63. }
  64. v2io.RawReaderToChan(output, conn)
  65. }()
  66. writeMutex.Lock()
  67. if tcpConn, ok := conn.(*net.TCPConn); ok {
  68. tcpConn.CloseWrite()
  69. }
  70. readMutex.Lock()
  71. return nil
  72. }