Ejemplo n.º 1
0
func (v *Server) handleConnection(connection internet.Connection) {
	defer connection.Close()

	timedReader := v2net.NewTimeOutReader(v.config.Timeout, connection)
	reader := bufio.NewReader(timedReader)
	defer reader.Release()

	writer := bufio.NewWriter(connection)
	defer writer.Release()

	auth, auth4, err := protocol.ReadAuthentication(reader)
	if err != nil && errors.Cause(err) != protocol.Socks4Downgrade {
		if errors.Cause(err) != io.EOF {
			log.Warning("Socks: failed to read authentication: ", err)
		}
		return
	}

	clientAddr := v2net.DestinationFromAddr(connection.RemoteAddr())
	if err != nil && err == protocol.Socks4Downgrade {
		v.handleSocks4(clientAddr, reader, writer, auth4)
	} else {
		v.handleSocks5(clientAddr, reader, writer, auth)
	}
}
Ejemplo n.º 2
0
func (s *Server) Process(ctx context.Context, network v2net.Network, conn internet.Connection) error {
	conn.SetReusable(false)

	timedReader := v2net.NewTimeOutReader(s.config.Timeout, conn)
	reader := bufio.OriginalReaderSize(timedReader, 2048)

	request, err := http.ReadRequest(reader)
	if err != nil {
		if errors.Cause(err) != io.EOF {
			log.Warning("HTTP: Failed to read http request: ", err)
		}
		return err
	}
	log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]")
	defaultPort := v2net.Port(80)
	if strings.ToLower(request.URL.Scheme) == "https" {
		defaultPort = v2net.Port(443)
	}
	host := request.Host
	if len(host) == 0 {
		host = request.URL.Host
	}
	dest, err := parseHost(host, defaultPort)
	if err != nil {
		log.Warning("HTTP: Malformed proxy host (", host, "): ", err)
		return err
	}
	log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "")
	ctx = proxy.ContextWithDestination(ctx, dest)
	if strings.ToUpper(request.Method) == "CONNECT" {
		return s.handleConnect(ctx, request, reader, conn)
	} else {
		return s.handlePlainHTTP(ctx, request, reader, conn)
	}
}
Ejemplo n.º 3
0
// PipeUntilEOF behaves the same as Pipe(). The only difference is PipeUntilEOF returns nil on EOF.
func PipeUntilEOF(reader Reader, writer Writer) error {
	err := Pipe(reader, writer)
	if err != nil && errors.Cause(err) != io.EOF {
		return err
	}
	return nil
}
Ejemplo n.º 4
0
// ReadFrom implements io.ReaderFrom.ReadFrom().
func (v *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
	totalBytes := int64(0)
	for {
		oriSize := v.buffer.Len()
		err := v.buffer.AppendSupplier(buf.ReadFrom(reader))
		totalBytes += int64(v.buffer.Len() - oriSize)
		if err != nil {
			if errors.Cause(err) == io.EOF {
				return totalBytes, nil
			}
			return totalBytes, err
		}
		if err := v.Flush(); err != nil {
			return totalBytes, err
		}
	}
}
Ejemplo n.º 5
0
func (v *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
	v.Lock()
	defer v.Unlock()

	if v.writer == nil {
		return 0, io.ErrClosedPipe
	}

	totalBytes := int64(0)
	for {
		oriSize := v.buffer.Len()
		err := v.buffer.AppendSupplier(buf.ReadFrom(reader))
		totalBytes += int64(v.buffer.Len() - oriSize)
		if err != nil {
			if errors.Cause(err) == io.EOF {
				return totalBytes, nil
			}
			return totalBytes, err
		}
		v.FlushWithoutLock()
	}
}
Ejemplo n.º 6
0
func (v *Server) handleConnection(conn internet.Connection) {
	defer conn.Close()
	timedReader := v2net.NewTimeOutReader(v.config.Timeout, conn)
	reader := bufio.OriginalReaderSize(timedReader, 2048)

	request, err := http.ReadRequest(reader)
	if err != nil {
		if errors.Cause(err) != io.EOF {
			log.Warning("HTTP: Failed to read http request: ", err)
		}
		return
	}
	log.Info("HTTP: Request to Method [", request.Method, "] Host [", request.Host, "] with URL [", request.URL, "]")
	defaultPort := v2net.Port(80)
	if strings.ToLower(request.URL.Scheme) == "https" {
		defaultPort = v2net.Port(443)
	}
	host := request.Host
	if len(host) == 0 {
		host = request.URL.Host
	}
	dest, err := parseHost(host, defaultPort)
	if err != nil {
		log.Warning("HTTP: Malformed proxy host (", host, "): ", err)
		return
	}
	log.Access(conn.RemoteAddr(), request.URL, log.AccessAccepted, "")
	session := &proxy.SessionInfo{
		Source:      v2net.DestinationFromAddr(conn.RemoteAddr()),
		Destination: dest,
		Inbound:     v.meta,
	}
	if strings.ToUpper(request.Method) == "CONNECT" {
		v.handleConnect(request, session, reader, conn)
	} else {
		v.handlePlainHTTP(request, session, reader, conn)
	}
}
Ejemplo n.º 7
0
func (ws *wsconn) readNext(b []byte) (n int, err error) {
	if ws.readBuffer == nil {
		err = ws.getNewReadBuffer()
		if err != nil {
			return 0, err
		}
	}

	n, err = ws.readBuffer.Read(b)

	if err == nil {
		return n, err
	}

	if errors.Cause(err) == io.EOF {
		ws.readBuffer = nil
		if n == 0 {
			return ws.readNext(b)
		}
		return n, nil
	}
	return n, err

}
Ejemplo n.º 8
0
func (v *VMessInboundHandler) Process(ctx context.Context, network net.Network, connection internet.Connection) error {
	connReader := net.NewTimeOutReader(8, connection)
	reader := bufio.NewReader(connReader)

	session := encoding.NewServerSession(v.clients)
	request, err := session.DecodeRequestHeader(reader)

	if err != nil {
		if errors.Cause(err) != io.EOF {
			log.Access(connection.RemoteAddr(), "", log.AccessRejected, err)
			log.Info("VMess|Inbound: Invalid request from ", connection.RemoteAddr(), ": ", err)
		}
		connection.SetReusable(false)
		return err
	}
	log.Access(connection.RemoteAddr(), request.Destination(), log.AccessAccepted, "")
	log.Info("VMess|Inbound: Received request for ", request.Destination())

	connection.SetReusable(request.Option.Has(protocol.RequestOptionConnectionReuse))

	ctx = proxy.ContextWithDestination(ctx, request.Destination())
	ctx = protocol.ContextWithUser(ctx, request.User)
	ray := v.packetDispatcher.DispatchToOutbound(ctx)

	input := ray.InboundInput()
	output := ray.InboundOutput()

	userSettings := request.User.GetSettings()
	connReader.SetTimeOut(userSettings.PayloadReadTimeout)
	reader.SetBuffered(false)

	requestDone := signal.ExecuteAsync(func() error {
		return transferRequest(session, request, reader, input)
	})

	writer := bufio.NewWriter(connection)
	response := &protocol.ResponseHeader{
		Command: v.generateCommand(ctx, request),
	}

	if connection.Reusable() {
		response.Option.Set(protocol.ResponseOptionConnectionReuse)
	}

	responseDone := signal.ExecuteAsync(func() error {
		return transferResponse(session, request, response, output, writer)
	})

	if err := signal.ErrorOrFinish2(requestDone, responseDone); err != nil {
		log.Info("VMess|Inbound: Connection ending with ", err)
		connection.SetReusable(false)
		input.CloseError()
		output.CloseError()
		return err
	}

	if err := writer.Flush(); err != nil {
		log.Info("VMess|Inbound: Failed to flush remain data: ", err)
		connection.SetReusable(false)
		return err
	}

	return nil
}