func MarshalCommand(command interface{}, writer io.Writer) error { if command == nil { return ErrUnknownCommand } var cmdId byte var factory CommandFactory switch command.(type) { case *protocol.CommandSwitchAccount: factory = new(CommandSwitchAccountFactory) cmdId = 1 default: return ErrUnknownCommand } buffer := alloc.NewLocalBuffer(512).Clear() defer buffer.Release() err := factory.Marshal(command, buffer) if err != nil { return err } auth := Authenticate(buffer.Value) len := buffer.Len() + 4 if len > 255 { return ErrCommandTooLarge } writer.Write([]byte{cmdId, byte(len), byte(auth >> 24), byte(auth >> 16), byte(auth >> 8), byte(auth)}) writer.Write(buffer.Value) return nil }
func (this *BufferedSegmentWriter) Write(seg Segment) { this.Lock() defer this.Unlock() nBytes := seg.ByteSize() if uint32(this.buffer.Len()+nBytes) > this.mtu { this.FlushWithoutLock() } if this.buffer == nil { this.buffer = alloc.NewLocalBuffer(2048).Clear() } this.buffer.Value = seg.Bytes(this.buffer.Value) }
func (this *Connection) FetchInputFrom(conn io.Reader) { go func() { payload := alloc.NewLocalBuffer(2048) defer payload.Release() for { payload.Reset() nBytes, err := conn.Read(payload.Value) if err != nil { return } payload.Slice(0, nBytes) if this.block.Open(payload) { this.Input(payload.Value) } } }() }
func (this *VMessInboundHandler) HandleConnection(connection internet.Connection) { defer connection.Close() if !this.accepting { return } connReader := v2net.NewTimeOutReader(8, connection) defer connReader.Release() reader := v2io.NewBufferedReader(connReader) defer reader.Release() this.RLock() if !this.accepting { this.RUnlock() return } session := encoding.NewServerSession(this.clients) defer session.Release() request, err := session.DecodeRequestHeader(reader) this.RUnlock() if err != nil { if err != io.EOF { log.Access(connection.RemoteAddr(), "", log.AccessRejected, err) log.Warning("VMessIn: Invalid request from ", connection.RemoteAddr(), ": ", err) } connection.SetReusable(false) return } log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "") log.Info("VMessIn: Received request for ", request.Destination()) connection.SetReusable(request.Option.Has(protocol.RequestOptionConnectionReuse)) ray := this.packetDispatcher.DispatchToOutbound(request.Destination()) input := ray.InboundInput() output := ray.InboundOutput() defer input.Close() defer output.Release() var readFinish sync.Mutex readFinish.Lock() userSettings := protocol.GetUserSettings(request.User.Level) connReader.SetTimeOut(userSettings.PayloadReadTimeout) reader.SetCached(false) go func() { bodyReader := session.DecodeRequestBody(reader) var requestReader v2io.Reader if request.Option.Has(protocol.RequestOptionChunkStream) { requestReader = vmessio.NewAuthChunkReader(bodyReader) } else { requestReader = v2io.NewAdaptiveReader(bodyReader) } err := v2io.Pipe(requestReader, input) if err != io.EOF { connection.SetReusable(false) } requestReader.Release() input.Close() readFinish.Unlock() }() writer := v2io.NewBufferedWriter(connection) defer writer.Release() response := &protocol.ResponseHeader{ Command: this.generateCommand(request), } if connection.Reusable() { response.Option.Set(protocol.ResponseOptionConnectionReuse) } session.EncodeResponseHeader(response, writer) bodyWriter := session.EncodeResponseBody(writer) var v2writer v2io.Writer = v2io.NewAdaptiveWriter(bodyWriter) if request.Option.Has(protocol.RequestOptionChunkStream) { v2writer = vmessio.NewAuthChunkWriter(v2writer) } // Optimize for small response packet if data, err := output.Read(); err == nil { if err := v2writer.Write(data); err != nil { connection.SetReusable(false) } writer.SetCached(false) err = v2io.Pipe(output, v2writer) if err != io.EOF { connection.SetReusable(false) } } output.Release() if request.Option.Has(protocol.RequestOptionChunkStream) { if err := v2writer.Write(alloc.NewLocalBuffer(32).Clear()); err != nil { connection.SetReusable(false) } } writer.Flush() v2writer.Release() readFinish.Lock() }
func (this *HTTPResponse) WriteTo(writer v2io.Writer) { writer.Write(alloc.NewLocalBuffer(512).Clear().AppendString(http403response)) }