freedom.go 1.9 KB

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