freedom.go 1.9 KB

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