func (handler *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray core.OutboundRay) error { input := ray.OutboundInput() output := ray.OutboundOutput() handler.Destination = packet.Destination() if packet.Chunk() != nil { handler.Data2Send.Write(packet.Chunk().Value) } go func() { for { data, open := <-input if !open { break } handler.Data2Send.Write(data.Value) data.Release() } response := alloc.NewBuffer() response.Clear() response.Append(handler.Data2Return) output <- response close(output) }() return nil }
func (handler *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray core.OutboundRay) error { input := ray.OutboundInput() output := ray.OutboundOutput() handler.Destination = packet.Destination() if packet.Chunk() != nil { handler.Data2Send.Write(packet.Chunk()) } go func() { for { data, open := <-input if !open { break } handler.Data2Send.Write(data) } dataCopy := make([]byte, len(handler.Data2Return)) copy(dataCopy, handler.Data2Return) output <- dataCopy close(output) }() return nil }
func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { vNextAddress, vNextUser := this.receiverManager.PickReceiver() command := protocol.CmdTCP if firstPacket.Destination().IsUDP() { command = protocol.CmdUDP } request := &protocol.VMessRequest{ Version: protocol.Version, User: vNextUser, Command: command, Address: firstPacket.Destination().Address(), Port: firstPacket.Destination().Port(), } if command == protocol.CmdUDP { request.Option |= protocol.OptionChunk } buffer := alloc.NewSmallBuffer() defer buffer.Release() // Buffer is released after communication finishes. io.ReadFull(rand.Reader, buffer.Value[:33]) // 16 + 16 + 1 request.RequestIV = buffer.Value[:16] request.RequestKey = buffer.Value[16:32] request.ResponseHeader = buffer.Value[32] return this.startCommunicate(request, vNextAddress, ray, firstPacket) }
func (this *OutboundConnectionHandler) Dispatch(packet v2net.Packet, ray ray.OutboundRay) error { input := ray.OutboundInput() output := ray.OutboundOutput() this.Destination = packet.Destination() if packet.Chunk() != nil { this.ConnOutput.Write(packet.Chunk().Value) packet.Chunk().Release() } if packet.MoreChunks() { writeFinish := &sync.Mutex{} writeFinish.Lock() go func() { v2io.ChanToRawWriter(this.ConnOutput, input) writeFinish.Unlock() }() writeFinish.Lock() } v2io.RawReaderToChan(output, this.ConnInput) close(output) return nil }
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { conn, err := net.Dial(firstPacket.Destination().Network(), firstPacket.Destination().Address().String()) log.Info("Freedom: Opening connection to %s", firstPacket.Destination().String()) if err != nil { close(ray.OutboundOutput()) log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err) return err } input := ray.OutboundInput() output := ray.OutboundOutput() var readMutex, writeMutex sync.Mutex readMutex.Lock() writeMutex.Lock() if chunk := firstPacket.Chunk(); chunk != nil { conn.Write(chunk.Value) chunk.Release() } if !firstPacket.MoreChunks() { writeMutex.Unlock() } else { go func() { v2net.ChanToWriter(conn, input) writeMutex.Unlock() }() } go func() { defer readMutex.Unlock() defer close(output) response, err := v2net.ReadFrom(conn, nil) log.Info("Freedom receives %d bytes from %s", response.Len(), conn.RemoteAddr().String()) if response.Len() > 0 { output <- response } else { response.Release() } if err != nil { return } if firstPacket.Destination().IsUDP() { return } v2net.ReaderToChan(output, conn) }() writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() conn.Close() return nil }
func (handler *OutboundConnectionHandler) Create(point *core.Point, packet v2net.Packet) (core.OutboundConnectionHandler, error) { handler.Destination = packet.Destination() if packet.Chunk() != nil { handler.Data2Send.Write(packet.Chunk()) } return handler, nil }
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { log.Info("Freedom: Opening connection to ", firstPacket.Destination()) var conn net.Conn err := retry.Timed(5, 100).On(func() error { rawConn, err := dialer.Dial(firstPacket.Destination()) if err != nil { return err } conn = rawConn return nil }) if err != nil { close(ray.OutboundOutput()) log.Error("Freedom: Failed to open connection to ", firstPacket.Destination(), ": ", err) return err } defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() var readMutex, writeMutex sync.Mutex readMutex.Lock() writeMutex.Lock() if chunk := firstPacket.Chunk(); chunk != nil { conn.Write(chunk.Value) chunk.Release() } if !firstPacket.MoreChunks() { writeMutex.Unlock() } else { go func() { v2io.ChanToRawWriter(conn, input) writeMutex.Unlock() }() } go func() { defer readMutex.Unlock() defer close(output) var reader io.Reader = conn if firstPacket.Destination().IsUDP() { reader = v2net.NewTimeOutReader(16 /* seconds */, conn) } v2io.RawReaderToChan(output, reader) }() writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() return nil }
func (this *UDPServer) Dispatch(source v2net.Destination, packet v2net.Packet, callback UDPResponseCallback) { destString := source.String() + "-" + packet.Destination().String() if this.locateExistingAndDispatch(destString, packet) { return } this.Lock() inboundRay := this.packetDispatcher.DispatchToOutbound(v2net.NewPacket(packet.Destination(), packet.Chunk(), true)) this.conns[destString] = &connEntry{ inboundRay: inboundRay, callback: callback, } this.Unlock() go this.handleConnection(destString, inboundRay, source, callback) }
// Dispatches a Packet to an OutboundConnection. // The packet will be passed through the router (if configured), and then sent to an outbound // connection with matching tag. func (this *Point) DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay { direct := ray.NewRay() dest := packet.Destination() dispatcher := this.och if this.router != nil { if tag, err := this.router.TakeDetour(dest); err == nil { if handler, found := this.odh[tag]; found { dispatcher = handler } } } go this.FilterPacketAndDispatch(packet, direct, dispatcher) return direct }
func (this *Point) DispatchToOutbound(packet v2net.Packet) ray.InboundRay { direct := ray.NewRay() dest := packet.Destination() if this.router != nil { tag, err := this.router.TakeDetour(dest) if err == nil { handler, found := this.odh[tag] if found { go handler.Dispatch(packet, direct) return direct } } } go this.och.Dispatch(packet, direct) return direct }
func (this *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { vNextAddress, vNextUser := this.receiverManager.PickReceiver() command := proto.RequestCommandTCP if firstPacket.Destination().IsUDP() { command = proto.RequestCommandUDP } request := &proto.RequestHeader{ Version: raw.Version, User: vNextUser, Command: command, Address: firstPacket.Destination().Address(), Port: firstPacket.Destination().Port(), } if command == proto.RequestCommandUDP { request.Option |= proto.RequestOptionChunkStream } return this.startCommunicate(request, vNextAddress, ray, firstPacket) }
// Dispatches a Packet to an OutboundConnection. // The packet will be passed through the router (if configured), and then sent to an outbound // connection with matching tag. func (this *Point) DispatchToOutbound(context app.Context, packet v2net.Packet) ray.InboundRay { direct := ray.NewRay() dest := packet.Destination() dispatcher := this.och if this.router != nil { if tag, err := this.router.TakeDetour(dest); err == nil { if handler, found := this.odh[tag]; found { log.Info("Point: Taking detour [", tag, "] for [", dest, "]", tag, dest) dispatcher = handler } else { log.Warning("Point: Unable to find routing destination: ", tag) } } } go this.FilterPacketAndDispatch(packet, direct, dispatcher) return direct }
func (this *Point) FilterPacketAndDispatch(packet v2net.Packet, link ray.OutboundRay, dispatcher proxy.OutboundConnectionHandler) { // Filter empty packets chunk := packet.Chunk() moreChunks := packet.MoreChunks() changed := false for chunk == nil && moreChunks { changed = true chunk, moreChunks = <-link.OutboundInput() } if chunk == nil && !moreChunks { close(link.OutboundOutput()) return } if changed { packet = v2net.NewPacket(packet.Destination(), chunk, moreChunks) } dispatcher.Dispatch(packet, link) }
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray core.OutboundRay) error { vNextList := handler.vNextList if firstPacket.Destination().IsUDP() { vNextList = handler.vNextListUDP } vNextAddress, vNextUser := pickVNext(vNextList) command := protocol.CmdTCP if firstPacket.Destination().IsUDP() { command = protocol.CmdUDP } request := &protocol.VMessRequest{ Version: protocol.Version, UserId: vNextUser.Id, Command: command, Address: firstPacket.Destination().Address(), } buffer := make([]byte, 36) // 16 + 16 + 4 rand.Read(buffer) request.RequestIV = buffer[:16] request.RequestKey = buffer[16:32] request.ResponseHeader = buffer[32:] go startCommunicate(request, vNextAddress, ray, firstPacket) return nil }
func (vconn *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray core.OutboundRay) error { conn, err := net.Dial(firstPacket.Destination().Network(), firstPacket.Destination().Address().String()) log.Info("Freedom: Opening connection to %s", firstPacket.Destination().String()) if err != nil { if ray != nil { close(ray.OutboundOutput()) } return log.Error("Freedom: Failed to open connection: %s : %v", firstPacket.Destination().String(), err) } input := ray.OutboundInput() output := ray.OutboundOutput() var readMutex, writeMutex sync.Mutex readMutex.Lock() writeMutex.Lock() if chunk := firstPacket.Chunk(); chunk != nil { conn.Write(chunk.Value) chunk.Release() } if !firstPacket.MoreChunks() { writeMutex.Unlock() } else { go dumpInput(conn, input, &writeMutex) } go dumpOutput(conn, output, &readMutex, firstPacket.Destination().IsUDP()) go func() { writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() conn.Close() }() return nil }
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { vNextList := handler.vNextList if firstPacket.Destination().IsUDP() { vNextList = handler.vNextListUDP } vNextAddress, vNextUser := pickVNext(vNextList) command := protocol.CmdTCP if firstPacket.Destination().IsUDP() { command = protocol.CmdUDP } request := &protocol.VMessRequest{ Version: protocol.Version, User: vNextUser, Command: command, Address: firstPacket.Destination().Address(), } buffer := alloc.NewSmallBuffer() defer buffer.Release() v2net.ReadAllBytes(rand.Reader, buffer.Value[:36]) // 16 + 16 + 4 request.RequestIV = buffer.Value[:16] request.RequestKey = buffer.Value[16:32] request.ResponseHeader = buffer.Value[32:36] return startCommunicate(request, vNextAddress, ray, firstPacket) }
func (handler *OutboundConnectionHandler) Create(point *core.Point, config []byte, packet v2net.Packet) (core.OutboundConnectionHandler, error) { handler.Destination = packet.Destination() return handler, nil }
func (this *FreedomConnection) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error { log.Info("Freedom: Opening connection to ", firstPacket.Destination()) var conn net.Conn err := retry.Timed(5, 100).On(func() error { rawConn, err := dialer.Dial(firstPacket.Destination()) if err != nil { return err } conn = rawConn return nil }) if err != nil { close(ray.OutboundOutput()) log.Error("Freedom: Failed to open connection to ", firstPacket.Destination(), ": ", err) return err } defer conn.Close() input := ray.OutboundInput() output := ray.OutboundOutput() var readMutex, writeMutex sync.Mutex readMutex.Lock() writeMutex.Lock() if chunk := firstPacket.Chunk(); chunk != nil { conn.Write(chunk.Value) chunk.Release() } if !firstPacket.MoreChunks() { writeMutex.Unlock() } else { go func() { v2net.ChanToWriter(conn, input) writeMutex.Unlock() }() } go func() { defer readMutex.Unlock() defer close(output) response, err := v2net.ReadFrom(conn, nil) log.Info("Freedom receives ", response.Len(), " bytes from ", conn.RemoteAddr()) if response.Len() > 0 { output <- response } else { response.Release() } if err != nil { return } if firstPacket.Destination().IsUDP() { return } v2net.ReaderToChan(output, conn) }() if this.space.HasDnsCache() { if firstPacket.Destination().Address().IsDomain() { domain := firstPacket.Destination().Address().Domain() addr := conn.RemoteAddr() switch typedAddr := addr.(type) { case *net.TCPAddr: this.space.DnsCache().Add(domain, typedAddr.IP) case *net.UDPAddr: this.space.DnsCache().Add(domain, typedAddr.IP) } } } writeMutex.Lock() if tcpConn, ok := conn.(*net.TCPConn); ok { tcpConn.CloseWrite() } readMutex.Lock() return nil }