Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bazel/envoy_mobile_test_extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ TEST_EXTENSIONS = [
"//library/common/extensions/filters/http/test_accessor:config",
"//library/common/extensions/filters/http/test_event_tracker:config",
"//library/common/extensions/filters/http/test_kv_store:config",
"//library/common/extensions/filters/http/test_read:config",
]
42 changes: 42 additions & 0 deletions library/common/extensions/filters/http/test_read/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
load(
"@envoy//bazel:envoy_build_system.bzl",
"envoy_cc_extension",
"envoy_extension_package",
"envoy_proto_library",
)

licenses(["notice"]) # Apache 2

envoy_extension_package()

envoy_proto_library(
name = "filter",
srcs = ["filter.proto"],
deps = [
"@envoy_api//envoy/config/common/matcher/v3:pkg",
],
)

envoy_cc_extension(
name = "test_read_filter_lib",
srcs = ["filter.cc"],
hdrs = ["filter.h"],
repository = "@envoy",
deps = [
"filter_cc_proto",
"@envoy//source/common/http:utility_lib",
"@envoy//source/common/stream_info:stream_info_lib",
"@envoy//source/extensions/filters/http/common:pass_through_filter_lib",
],
)

envoy_cc_extension(
name = "config",
srcs = ["config.cc"],
hdrs = ["config.h"],
repository = "@envoy",
deps = [
":test_read_filter_lib",
"@envoy//source/extensions/filters/http/common:factory_base_lib",
],
)
26 changes: 26 additions & 0 deletions library/common/extensions/filters/http/test_read/config.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "library/common/extensions/filters/http/test_read/config.h"

#include "library/common/extensions/filters/http/test_read/filter.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace TestRead {

Http::FilterFactoryCb TestReadFilterFactory::createFilterFactoryFromProtoTyped(
const envoymobile::extensions::filters::http::test_read::TestRead& /*config*/,
const std::string&, Server::Configuration::FactoryContext& /*context*/) {
return [](Http::FilterChainFactoryCallbacks& callbacks) -> void {
callbacks.addStreamDecoderFilter(std::make_shared<TestReadFilter>());
};
}

/**
* Static registration for the TestRead filter. @see NamedHttpFilterConfigFactory.
*/
REGISTER_FACTORY(TestReadFilterFactory, Server::Configuration::NamedHttpFilterConfigFactory);

} // namespace TestRead
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
34 changes: 34 additions & 0 deletions library/common/extensions/filters/http/test_read/config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <string>

#include "source/extensions/filters/http/common/factory_base.h"

#include "library/common/extensions/filters/http/test_read/filter.pb.h"
#include "library/common/extensions/filters/http/test_read/filter.pb.validate.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace TestRead {

/**
* Config registration for the TestRead filter. @see NamedHttpFilterConfigFactory.
*/
class TestReadFilterFactory
: public Common::FactoryBase<envoymobile::extensions::filters::http::test_read::TestRead> {
public:
TestReadFilterFactory() : FactoryBase("test_read") {}

private:
::Envoy::Http::FilterFactoryCb createFilterFactoryFromProtoTyped(
const envoymobile::extensions::filters::http::test_read::TestRead& config,
const std::string& stats_prefix, Server::Configuration::FactoryContext& context) override;
};

DECLARE_FACTORY(TestReadFilterFactory);

} // namespace TestRead
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
46 changes: 46 additions & 0 deletions library/common/extensions/filters/http/test_read/filter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "library/common/extensions/filters/http/test_read/filter.h"

#include "envoy/server/filter_config.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace TestRead {

Http::FilterHeadersStatus TestReadFilter::decodeHeaders(Http::RequestHeaderMap& request_headers,
bool) {
// sample path is /failed?start=0x10000
Http::Utility::QueryParams query_parameters =
Http::Utility::parseQueryString(request_headers.Path()->value().getStringView());
uint64_t response_flag;
if (absl::SimpleAtoi(query_parameters.at("start"), &response_flag)) {
decoder_callbacks_->streamInfo().setResponseFlag(
TestReadFilter::mapErrorToResponseFlag(response_flag));
decoder_callbacks_->sendLocalReply(Http::Code::BadRequest, "test_read filter threw: ", nullptr,
absl::nullopt, "");
}
return Http::FilterHeadersStatus::StopIteration;
}

StreamInfo::ResponseFlag TestReadFilter::mapErrorToResponseFlag(uint64_t errorCode) {
switch (errorCode) {
case 0x4000000:
Comment thread
colibie marked this conversation as resolved.
return StreamInfo::DnsResolutionFailed;
case 0x40:
return StreamInfo::UpstreamConnectionTermination;
case 0x20:
return StreamInfo::UpstreamConnectionFailure;
case 0x10:
return StreamInfo::UpstreamRemoteReset;
case 0x10000:
return StreamInfo::StreamIdleTimeout;
default:
// Any other error that we aren't interested in. I picked a random error.
return StreamInfo::RateLimitServiceError;
}
}

} // namespace TestRead
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
35 changes: 35 additions & 0 deletions library/common/extensions/filters/http/test_read/filter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "envoy/http/filter.h"

#include "source/common/common/logger.h"
#include "source/common/http/utility.h"
#include "source/common/stream_info/stream_info_impl.h"
#include "source/extensions/filters/http/common/pass_through_filter.h"

#include "library/common/extensions/filters/http/test_read/filter.pb.h"

namespace Envoy {
namespace Extensions {
namespace HttpFilters {
namespace TestRead {

/**
* Filter to return specified error code based on a request header.
Comment thread
colibie marked this conversation as resolved.
Outdated
*/
class TestReadFilter final : public Http::PassThroughFilter,
Comment thread
colibie marked this conversation as resolved.
public Logger::Loggable<Logger::Id::filter> {
public:
Http::FilterHeadersStatus decodeHeaders(Http::RequestHeaderMap& request_headers, bool) override;

private:
/* A mapping of the envoymobile errors we care about for testing
* From https://github.com/envoyproxy/envoy/blob/main/envoy/stream_info/stream_info.h
*/
StreamInfo::ResponseFlag mapErrorToResponseFlag(uint64_t errorCode);
};

} // namespace TestRead
} // namespace HttpFilters
} // namespace Extensions
} // namespace Envoy
8 changes: 8 additions & 0 deletions library/common/extensions/filters/http/test_read/filter.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
syntax = "proto3";

package envoymobile.extensions.filters.http.test_read;

import "validate/validate.proto";

message TestRead {
}
10 changes: 0 additions & 10 deletions library/java/org/chromium/net/impl/Annotations.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,6 @@ public final class Annotations {
int HIGHEST = 5;
}

/** Subset of errors defined in chromium/src/net/base/net_error_list.h */
@IntDef({NetError.ERR_HTTP2_PING_FAILED, NetError.ERR_QUIC_HANDSHAKE_FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface NetError {
int ERR_NETWORK_CHANGED = -21;
int ERR_HTTP2_PING_FAILED = -352;
int ERR_QUIC_PROTOCOL_ERROR = -356;
int ERR_QUIC_HANDSHAKE_FAILED = -358;
}

/** Enum defined here: chromium/src/components/cronet/url_request_context_config.h, line 37 */
@IntDef({HttpCacheType.DISABLED, HttpCacheType.DISK, HttpCacheType.MEMORY})
@Retention(RetentionPolicy.SOURCE)
Expand Down
1 change: 1 addition & 0 deletions library/java/org/chromium/net/impl/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ android_library(
"CronetUploadDataStream.java",
"CronetUrlRequest.java",
"CronetUrlRequestContext.java",
"Errors.java",
"Executors.java",
"HttpReason.java",
"ImplVersion.java",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.chromium.net.impl;

import org.chromium.net.impl.Annotations.NetError;
import org.chromium.net.impl.Errors.NetError;

/**
* Used in {@link CronetBidirectionalStream}. Implements {@link NetworkExceptionImpl}.
Expand All @@ -13,13 +13,11 @@ public BidirectionalStreamNetworkException(String message, int errorCode,

@Override
public boolean immediatelyRetryable() {
switch (mCronetInternalErrorCode) {
case NetError.ERR_HTTP2_PING_FAILED:
case NetError.ERR_QUIC_HANDSHAKE_FAILED:
if (mCronetInternalErrorCode == NetError.ERR_HTTP2_PING_FAILED.getErrorCode() ||
mCronetInternalErrorCode == NetError.ERR_QUIC_HANDSHAKE_FAILED.getErrorCode()) {
assert mErrorCode == ERROR_OTHER;
return true;
default:
return super.immediatelyRetryable();
}
return super.immediatelyRetryable();
}
}
29 changes: 17 additions & 12 deletions library/java/org/chromium/net/impl/CronetBidirectionalStream.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.chromium.net.impl;

import static org.chromium.net.impl.Errors.mapEnvoyMobileErrorToNetError;
import static org.chromium.net.impl.Errors.mapNetErrorToCronetApiErrorCode;

import android.util.Log;

import androidx.annotation.Nullable;
Expand All @@ -15,6 +18,7 @@
import org.chromium.net.impl.Annotations.RequestPriority;
import org.chromium.net.impl.CronetBidirectionalState.Event;
import org.chromium.net.impl.CronetBidirectionalState.NextAction;
import org.chromium.net.impl.Errors.NetError;
import org.chromium.net.impl.UrlResponseInfoImpl.HeaderBlockImpl;

import java.net.MalformedURLException;
Expand Down Expand Up @@ -643,21 +647,24 @@ public void run() {
});
}

private void onErrorReceived(int errorCode, int nativeError, int nativeQuicError,
String errorString, long receivedByteCount) {
private void onErrorReceived(int errorCode, EnvoyFinalStreamIntel finalStreamIntel) {
if (mResponseInfo != null) {
mResponseInfo.setReceivedByteCount(receivedByteCount);
mResponseInfo.setReceivedByteCount(finalStreamIntel.getReceivedByteCount());
}
CronetException exception;

NetError netError = mapEnvoyMobileErrorToNetError(finalStreamIntel.getResponseFlags());
int javaError = mapNetErrorToCronetApiErrorCode(netError);
if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED ||
errorCode == NetworkException.ERROR_NETWORK_CHANGED) {
exception = new QuicExceptionImpl("Exception in BidirectionalStream: " + errorString,
errorCode, nativeError, nativeQuicError);
mException.set(
new QuicExceptionImpl("Exception in BidirectionalStream: " + netError.getModifiedString(),
javaError, netError.getErrorCode(), /*nativeQuicError*/ 0));
} else {
exception = new BidirectionalStreamNetworkException(
"Exception in BidirectionalStream: " + errorString, errorCode, nativeError);
mException.set(new BidirectionalStreamNetworkException("Exception in BidirectionalStream: " +
netError.getModifiedString(),
javaError, netError.getErrorCode()));
}
mException.set(exception);

failWithException();
}

Expand Down Expand Up @@ -1031,9 +1038,7 @@ public void onError(int errorCode, String message, int attemptCount, EnvoyStream
mEnvoyFinalStreamIntel = finalStreamIntel;
switch (mState.nextAction(Event.ON_ERROR)) {
case NextAction.NOTIFY_USER_NETWORK_ERROR:
// TODO(https://github.com/envoyproxy/envoy-mobile/issues/1594): fix error scheme.
onErrorReceived(errorCode, /* nativeError= */ -1,
/* nativeQuicError */ 0, message, finalStreamIntel.getReceivedByteCount());
onErrorReceived(errorCode, finalStreamIntel);
break;
case NextAction.NOTIFY_USER_FAILED:
// There was already an error in-progress - the network error came too late and is ignored.
Expand Down
22 changes: 19 additions & 3 deletions library/java/org/chromium/net/impl/CronetUrlRequest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.chromium.net.impl;

import static org.chromium.net.impl.Errors.mapEnvoyMobileErrorToNetError;
import static org.chromium.net.impl.Errors.mapNetErrorToCronetApiErrorCode;

import android.os.ConditionVariable;
import android.util.Log;
import androidx.annotation.IntDef;
Expand Down Expand Up @@ -30,9 +33,11 @@
import org.chromium.net.CallbackException;
import org.chromium.net.CronetException;
import org.chromium.net.InlineExecutionProhibitedException;
import org.chromium.net.NetworkException;
import org.chromium.net.RequestFinishedInfo;
import org.chromium.net.RequestFinishedInfo.Metrics;
import org.chromium.net.UploadDataProvider;
import org.chromium.net.impl.Errors.NetError;

/** UrlRequest, backed by Envoy-Mobile. */
public final class CronetUrlRequest extends UrlRequestBase {
Expand Down Expand Up @@ -927,9 +932,20 @@ public void onError(int errorCode, String message, int attemptCount,
return;
}

String errorMessage = "failed with error after " + attemptCount + " attempts. Message=[" +
message + "] Code=[" + errorCode + "]";
CronetException exception = new CronetExceptionImpl(errorMessage, /* cause= */ null);
NetError netError = mapEnvoyMobileErrorToNetError(finalStreamIntel.getResponseFlags());
int javaError = mapNetErrorToCronetApiErrorCode(netError);
CronetException exception;
if (errorCode == NetworkException.ERROR_QUIC_PROTOCOL_FAILED ||
Comment thread
colibie marked this conversation as resolved.
Outdated
errorCode == NetworkException.ERROR_NETWORK_CHANGED) {
exception =
new QuicExceptionImpl("Exception in CronetUrlRequest: " + netError.getModifiedString(),
javaError, netError.getErrorCode(), /*nativeQuicError*/ 0);
} else {
exception = new NetworkExceptionImpl("Exception in CronetUrlRequest: " +
netError.getModifiedString(),
javaError, netError.getErrorCode());
}

enterErrorState(exception); // No-op if already in a terminal state.
}

Expand Down
Loading