| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- package freedom
- import (
- "net"
- "sync"
- "github.com/v2ray/v2ray-core"
- "github.com/v2ray/v2ray-core/common/log"
- v2net "github.com/v2ray/v2ray-core/common/net"
- )
- type FreedomConnection struct {
- packet v2net.Packet
- }
- func NewFreedomConnection(firstPacket v2net.Packet) *FreedomConnection {
- return &FreedomConnection{
- packet: firstPacket,
- }
- }
- func (vconn *FreedomConnection) Start(ray core.OutboundRay) error {
- conn, err := net.Dial(vconn.packet.Destination().Network(), vconn.packet.Destination().Address().String())
- log.Info("Freedom: Opening connection to %s", vconn.packet.Destination().String())
- if err != nil {
- if ray != nil {
- close(ray.OutboundOutput())
- }
- return log.Error("Freedom: Failed to open connection: %s : %v", vconn.packet.Destination().String(), err)
- }
- input := ray.OutboundInput()
- output := ray.OutboundOutput()
- var readMutex, writeMutex sync.Mutex
- readMutex.Lock()
- writeMutex.Lock()
- if chunk := vconn.packet.Chunk(); chunk != nil {
- conn.Write(chunk)
- }
- if !vconn.packet.MoreChunks() {
- writeMutex.Unlock()
- } else {
- go dumpInput(conn, input, &writeMutex)
- }
- go dumpOutput(conn, output, &readMutex, vconn.packet.Destination().IsUDP())
- go func() {
- writeMutex.Lock()
- if tcpConn, ok := conn.(*net.TCPConn); ok {
- tcpConn.CloseWrite()
- }
- readMutex.Lock()
- conn.Close()
- }()
- return nil
- }
- func dumpInput(conn net.Conn, input <-chan []byte, finish *sync.Mutex) {
- v2net.ChanToWriter(conn, input)
- finish.Unlock()
- }
- func dumpOutput(conn net.Conn, output chan<- []byte, finish *sync.Mutex, udp bool) {
- defer finish.Unlock()
- defer close(output)
- response, err := v2net.ReadFrom(conn)
- log.Info("Freedom receives %d bytes from %s", len(response), conn.RemoteAddr().String())
- if len(response) > 0 {
- output <- response
- }
- if err != nil {
- return
- }
- if udp {
- return
- }
- v2net.ReaderToChan(output, conn)
- }
|