Commit ae7c9f4d authored by jingzhao@chromium.org's avatar jingzhao@chromium.org

Upstream: Build net_unittests for Android.


BUG=
TEST=


Review URL: http://codereview.chromium.org/8429034

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110902 0039d316-1c4b-4281-b951-d872f2087c98
parent 3d40d9e2
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
4018, 4018,
], ],
'conditions': [ 'conditions': [
[ 'os_posix == 1 and OS != "mac"', { [ 'os_posix == 1 and OS != "mac" and OS != "android"', {
'dependencies': [ 'dependencies': [
'../build/linux/system.gyp:ssl', '../build/linux/system.gyp:ssl',
], ],
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
}, },
], ],
], ],
}, { # os_posix != 1 or OS == "mac" }, { # os_posix != 1 or OS == "mac" or OS == "android"
'sources/': [ 'sources/': [
['exclude', '_nss\.cc$'], ['exclude', '_nss\.cc$'],
['include', 'ec_private_key_nss\.cc$'], ['include', 'ec_private_key_nss\.cc$'],
...@@ -44,6 +44,14 @@ ...@@ -44,6 +44,14 @@
'openpgp_symmetric_encryption.cc', 'openpgp_symmetric_encryption.cc',
], ],
}], }],
[ 'OS == "android"', {
'dependencies': [
'../build/android/system.gyp:ssl',
],
'sources/': [
['exclude', 'ec_private_key_nss\.cc$'],
],
}],
[ 'OS == "freebsd" or OS == "openbsd"', { [ 'OS == "freebsd" or OS == "openbsd"', {
'link_settings': { 'link_settings': {
'libraries': [ 'libraries': [
......
...@@ -185,7 +185,7 @@ void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val, ...@@ -185,7 +185,7 @@ void PrivateKeyInfoCodec::PrependIntegerImpl(uint8* val,
std::vector<uint8> tmp; std::vector<uint8> tmp;
if (!big_endian) { if (!big_endian) {
tmp.assign(val, val + num_bytes); tmp.assign(val, val + num_bytes);
reverse(tmp.begin(), tmp.end()); std::reverse(tmp.begin(), tmp.end());
val = &tmp.front(); val = &tmp.front();
} }
...@@ -240,7 +240,7 @@ bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos, ...@@ -240,7 +240,7 @@ bool PrivateKeyInfoCodec::ReadIntegerWithExpectedSize(uint8** pos,
// Reverse output if little-endian. // Reverse output if little-endian.
if (!big_endian_) if (!big_endian_)
reverse(out->begin(), out->end()); std::reverse(out->begin(), out->end());
return true; return true;
} }
...@@ -265,7 +265,7 @@ bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos, ...@@ -265,7 +265,7 @@ bool PrivateKeyInfoCodec::ReadIntegerImpl(uint8** pos,
// Reverse output if little-endian. // Reverse output if little-endian.
if (!big_endian) if (!big_endian)
reverse(out->begin(), out->end()); std::reverse(out->begin(), out->end());
return true; return true;
} }
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
#include "net/base/dns_reloader.h" #include "net/base/dns_reloader.h"
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) && \
!defined(OS_ANDROID)
#include <resolv.h> #include <resolv.h>
...@@ -34,6 +35,9 @@ namespace { ...@@ -34,6 +35,9 @@ namespace {
// the same trick there and most *BSD's don't yet have support for // the same trick there and most *BSD's don't yet have support for
// FilePathWatcher (but perhaps the new kqueue mac code just needs to be // FilePathWatcher (but perhaps the new kqueue mac code just needs to be
// ported to *BSD to support that). // ported to *BSD to support that).
//
// Android does not have /etc/resolv.conf. The system takes care of nameserver
// changes, so none of this is needed.
class DnsReloader : public net::NetworkChangeNotifier::DNSObserver { class DnsReloader : public net::NetworkChangeNotifier::DNSObserver {
public: public:
...@@ -119,4 +123,5 @@ void DnsReloaderMaybeReload() { ...@@ -119,4 +123,5 @@ void DnsReloaderMaybeReload() {
} // namespace net } // namespace net
#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) #endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) &&
// !defined(OS_ANDROID)
...@@ -176,7 +176,13 @@ class RRResolverWorker { ...@@ -176,7 +176,13 @@ class RRResolverWorker {
private: private:
#if defined(OS_POSIX) #if defined(OS_ANDROID)
void Run() {
NOTIMPLEMENTED();
}
#elif defined(OS_POSIX)
void Run() { void Run() {
// Runs on a worker thread. // Runs on a worker thread.
...@@ -404,9 +410,9 @@ bool RRResponse::HasExpired(const base::Time current_time) const { ...@@ -404,9 +410,9 @@ bool RRResponse::HasExpired(const base::Time current_time) const {
return current_time >= expiry; return current_time >= expiry;
} }
#if defined(OS_POSIX) && !defined(OS_ANDROID)
bool RRResponse::ParseFromResponse(const uint8* p, unsigned len, bool RRResponse::ParseFromResponse(const uint8* p, unsigned len,
uint16 rrtype_requested) { uint16 rrtype_requested) {
#if defined(OS_POSIX)
name.clear(); name.clear();
ttl = 0; ttl = 0;
dnssec = false; dnssec = false;
...@@ -485,10 +491,10 @@ bool RRResponse::ParseFromResponse(const uint8* p, unsigned len, ...@@ -485,10 +491,10 @@ bool RRResponse::ParseFromResponse(const uint8* p, unsigned len,
signatures.push_back(std::string(rrdata.data(), rrdata.size())); signatures.push_back(std::string(rrdata.data(), rrdata.size()));
} }
} }
#endif // defined(OS_POSIX)
return true; return true;
} }
#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
// An RRResolverJob is a one-to-one counterpart of an RRResolverWorker. It // An RRResolverJob is a one-to-one counterpart of an RRResolverWorker. It
......
...@@ -31,9 +31,11 @@ struct NET_EXPORT_PRIVATE RRResponse { ...@@ -31,9 +31,11 @@ struct NET_EXPORT_PRIVATE RRResponse {
// |current_time|. // |current_time|.
bool HasExpired(base::Time current_time) const; bool HasExpired(base::Time current_time) const;
#if defined(OS_POSIX) && !defined(OS_ANDROID)
// For testing only // For testing only
bool ParseFromResponse(const uint8* data, unsigned len, bool ParseFromResponse(const uint8* data, unsigned len,
uint16 rrtype_requested); uint16 rrtype_requested);
#endif
// name contains the canonical name of the resulting domain. If the queried // name contains the canonical name of the resulting domain. If the queried
// name was a CNAME then this can differ. // name was a CNAME then this can differ.
......
...@@ -119,7 +119,7 @@ TEST(DnsRRResolverTest, Resolve) { ...@@ -119,7 +119,7 @@ TEST(DnsRRResolverTest, Resolve) {
ASSERT_EQ(1u, resolver.inflight_joins()); ASSERT_EQ(1u, resolver.inflight_joins());
} }
#if defined(OS_POSIX) #if defined(OS_POSIX) && !defined(OS_ANDROID)
// This is a DNS packet resulting from querying a recursive resolver for a TXT // This is a DNS packet resulting from querying a recursive resolver for a TXT
// record for agl._pka.imperialviolet.org. You should be able to get a // record for agl._pka.imperialviolet.org. You should be able to get a
// replacement from a packet capture should it ever be needed. // replacement from a packet capture should it ever be needed.
......
...@@ -1082,7 +1082,9 @@ HostResolverImpl::HostResolverImpl( ...@@ -1082,7 +1082,9 @@ HostResolverImpl::HostResolverImpl(
#endif #endif
NetworkChangeNotifier::AddIPAddressObserver(this); NetworkChangeNotifier::AddIPAddressObserver(this);
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD) #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_OPENBSD)
#if !defined(OS_ANDROID)
EnsureDnsReloaderInit(); EnsureDnsReloaderInit();
#endif
NetworkChangeNotifier::AddDNSObserver(this); NetworkChangeNotifier::AddDNSObserver(this);
#endif #endif
} }
......
...@@ -1215,7 +1215,7 @@ TEST(NetUtilTest, GenerateSafeFileName) { ...@@ -1215,7 +1215,7 @@ TEST(NetUtilTest, GenerateSafeFileName) {
} }
TEST(NetUtilTest, GenerateFileName) { TEST(NetUtilTest, GenerateFileName) {
#if defined(OS_POSIX) && !defined(OS_MACOSX) #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
// This test doesn't run when the locale is not UTF-8 because some of the // This test doesn't run when the locale is not UTF-8 because some of the
// string conversions fail. This is OK (we have the default value) but they // string conversions fail. This is OK (we have the default value) but they
// don't match our expectations. // don't match our expectations.
......
...@@ -20,12 +20,18 @@ namespace net { ...@@ -20,12 +20,18 @@ namespace net {
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
bool PlatformMimeUtil::GetPlatformMimeTypeFromExtension( bool PlatformMimeUtil::GetPlatformMimeTypeFromExtension(
const FilePath::StringType& ext, std::string* result) const { const FilePath::StringType& ext, std::string* result) const {
// TODO(jingzhao): Recover the original implementation once we support JNI.
#if 0
return android::GetMimeTypeFromExtension(ext, result); return android::GetMimeTypeFromExtension(ext, result);
#else
NOTIMPLEMENTED();
return false;
#endif
} }
#else #else
bool PlatformMimeUtil::GetPlatformMimeTypeFromExtension( bool PlatformMimeUtil::GetPlatformMimeTypeFromExtension(
const FilePath::StringType& ext, std::string* result) const { const FilePath::StringType& ext, std::string* result) const {
// TODO(thestig) This is a temporary hack until we can fix this // TODO(thestig): This is a temporary hack until we can fix this
// properly in test shell / webkit. // properly in test shell / webkit.
// We have to play dumb and not return application/x-perl here // We have to play dumb and not return application/x-perl here
// to make the reload-subframe-object layout test happy. // to make the reload-subframe-object layout test happy.
......
...@@ -25,6 +25,11 @@ ...@@ -25,6 +25,11 @@
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/base/x509_util_openssl.h" #include "net/base/x509_util_openssl.h"
#if defined(OS_ANDROID)
#include "base/logging.h"
#include "net/android/network_library.h"
#endif
namespace net { namespace net {
namespace { namespace {
...@@ -511,8 +516,46 @@ X509_STORE* X509Certificate::cert_store() { ...@@ -511,8 +516,46 @@ X509_STORE* X509Certificate::cert_store() {
return X509InitSingleton::GetInstance()->store(); return X509InitSingleton::GetInstance()->store();
} }
#if !defined(OS_ANDROID) #if defined(OS_ANDROID)
int X509Certificate::VerifyInternal(const std::string& hostname,
int flags,
CRLSet* crl_set,
CertVerifyResult* verify_result) const {
if (!VerifyNameMatch(hostname))
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
std::vector<std::string> cert_bytes;
GetChainDEREncodedBytes(&cert_bytes);
// TODO(joth): Fetch the authentication type from SSL rather than hardcode.
// TODO(jingzhao): Recover the original implementation once we support JNI.
#if 0
android::VerifyResult result =
android::VerifyX509CertChain(cert_bytes, hostname, "RSA");
#else
android::VerifyResult result = android::VERIFY_INVOCATION_ERROR;
NOTIMPLEMENTED();
#endif
switch (result) {
case android::VERIFY_OK:
break;
case android::VERIFY_BAD_HOSTNAME:
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
break;
case android::VERIFY_NO_TRUSTED_ROOT:
verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
break;
case android::VERIFY_INVOCATION_ERROR:
default:
verify_result->cert_status |= ERR_CERT_INVALID;
break;
}
if (IsCertStatusError(verify_result->cert_status))
return MapCertStatusToNetError(verify_result->cert_status);
return OK;
}
#else
int X509Certificate::VerifyInternal(const std::string& hostname, int X509Certificate::VerifyInternal(const std::string& hostname,
int flags, int flags,
CRLSet* crl_set, CRLSet* crl_set,
...@@ -564,7 +607,7 @@ int X509Certificate::VerifyInternal(const std::string& hostname, ...@@ -564,7 +607,7 @@ int X509Certificate::VerifyInternal(const std::string& hostname,
return OK; return OK;
} }
#endif // !defined(OS_ANDROID) #endif // defined(OS_ANDROID)
// static // static
bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
...@@ -619,4 +662,23 @@ bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, ...@@ -619,4 +662,23 @@ bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
der_cache.data_length); der_cache.data_length);
} }
#if defined(OS_ANDROID)
void X509Certificate::GetChainDEREncodedBytes(
std::vector<std::string>* chain_bytes) const {
OSCertHandles cert_handles(intermediate_ca_certs_);
// Make sure the peer's own cert is the first in the chain, if it's not
// already there.
if (cert_handles.empty() || cert_handles[0] != cert_handle_)
cert_handles.insert(cert_handles.begin(), cert_handle_);
chain_bytes->reserve(cert_handles.size());
for (OSCertHandles::const_iterator it = cert_handles.begin();
it != cert_handles.end(); ++it) {
std::string cert_bytes;
GetDEREncoded(*it, &cert_bytes);
chain_bytes->push_back(cert_bytes);
}
}
#endif
} // namespace net } // namespace net
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/x509_certificate.h"
#include "base/logging.h"
#include "net/android/network_library.h"
#include "net/base/cert_status_flags.h"
#include "net/base/cert_verify_result.h"
#include "net/base/net_errors.h"
namespace net {
int X509Certificate::VerifyInternal(const std::string& hostname,
int flags,
CRLSet* crl_set,
CertVerifyResult* verify_result) const {
if (!VerifyNameMatch(hostname))
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
std::vector<std::string> cert_bytes;
GetChainDEREncodedBytes(&cert_bytes);
// TODO(joth): Fetch the authentication type from SSL rather than hardcode.
android::VerifyResult result =
android::VerifyX509CertChain(cert_bytes, hostname, "RSA");
switch (result) {
case android::VERIFY_OK:
return OK;
case android::VERIFY_BAD_HOSTNAME:
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
break;
case android::VERIFY_NO_TRUSTED_ROOT:
verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
break;
case android::VERIFY_INVOCATION_ERROR:
default:
verify_result->cert_status |= ERR_CERT_INVALID;
break;
}
return MapCertStatusToNetError(verify_result->cert_status);
}
void X509Certificate::GetChainDEREncodedBytes(
std::vector<std::string>* chain_bytes) const {
OSCertHandles cert_handles(intermediate_ca_certs_);
// Make sure the peer's own cert is the first in the chain, if it's not
// already there.
if (cert_handles.empty())
cert_handles.insert(cert_handles.begin(), cert_handle_);
chain_bytes->reserve(cert_handles.size());
for (OSCertHandles::const_iterator it = cert_handles.begin();
it != cert_handles.end(); ++it) {
DERCache der_cache = {0};
GetDERAndCacheIfNeeded(*it, &der_cache);
std::string cert_bytes (
reinterpret_cast<const char*>(der_cache.data), der_cache.data_length);
chain_bytes->push_back(cert_bytes);
}
}
} // namespace net
...@@ -30,24 +30,28 @@ class DnsConfigServicePosix::ConfigReader : public SerialWorker { ...@@ -30,24 +30,28 @@ class DnsConfigServicePosix::ConfigReader : public SerialWorker {
success_(false) {} success_(false) {}
void DoWork() OVERRIDE { void DoWork() OVERRIDE {
success_ = false;
#if defined(OS_ANDROID)
NOTIMPLEMENTED();
#else
#if defined(OS_OPENBSD) #if defined(OS_OPENBSD)
// Note: res_ninit in glibc always returns 0 and sets RES_INIT.
// res_init behaves the same way.
if ((res_init() == 0) && (_res.options & RES_INIT)) { if ((res_init() == 0) && (_res.options & RES_INIT)) {
success_ = ConvertResToConfig(_res, &dns_config_); success_ = ConvertResToConfig(_res, &dns_config_);
}
#else #else
struct __res_state res; struct __res_state res;
if ((res_ninit(&res) == 0) && (res.options & RES_INIT)) { if ((res_ninit(&res) == 0) && (res.options & RES_INIT)) {
success_ = ConvertResToConfig(res, &dns_config_); success_ = ConvertResToConfig(res, &dns_config_);
#endif
} else {
// Note: res_ninit in glibc always returns 0 and sets RES_INIT.
// res_init behaves the same way.
success_ = false;
} }
#endif
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
res_ndestroy(&res); res_ndestroy(&res);
#elif !defined(OS_OPENBSD) #elif !defined(OS_OPENBSD)
res_nclose(&res); res_nclose(&res);
#endif #endif
#endif // defined(OS_ANDROID)
} }
void OnWorkFinished() OVERRIDE { void OnWorkFinished() OVERRIDE {
...@@ -84,6 +88,7 @@ DnsConfigService* DnsConfigService::CreateSystemService() { ...@@ -84,6 +88,7 @@ DnsConfigService* DnsConfigService::CreateSystemService() {
return new DnsConfigServicePosix(); return new DnsConfigServicePosix();
} }
#if !defined(OS_ANDROID)
bool ConvertResToConfig(const struct __res_state& res, DnsConfig* dns_config) { bool ConvertResToConfig(const struct __res_state& res, DnsConfig* dns_config) {
CHECK(dns_config != NULL); CHECK(dns_config != NULL);
DCHECK(res.options & RES_INIT); DCHECK(res.options & RES_INIT);
...@@ -136,5 +141,6 @@ bool ConvertResToConfig(const struct __res_state& res, DnsConfig* dns_config) { ...@@ -136,5 +141,6 @@ bool ConvertResToConfig(const struct __res_state& res, DnsConfig* dns_config) {
return true; return true;
} }
#endif // !defined(OS_ANDROID)
} // namespace net } // namespace net
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
'linux_link_kerberos%': 0, 'linux_link_kerberos%': 0,
'conditions': [ 'conditions': [
['chromeos==1', { ['chromeos==1 or OS=="android"', {
# Disable Kerberos on ChromeOS, at least for now. # Disable Kerberos on ChromeOS and Android, at least for now.
# It needs configuration (krb5.conf and so on). # It needs configuration (krb5.conf and so on).
'use_kerberos%': 0, 'use_kerberos%': 0,
}, { # chromeos == 0 }, { # chromeos == 0
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
'ssl_false_start_blacklist_process#host', 'ssl_false_start_blacklist_process#host',
], ],
'sources': [ 'sources': [
'android/network_library.cc',
'android/network_library.h',
'base/address_family.h', 'base/address_family.h',
'base/address_list.cc', 'base/address_list.cc',
'base/address_list.h', 'base/address_list.h',
...@@ -185,6 +187,7 @@ ...@@ -185,6 +187,7 @@
'base/nss_memio.h', 'base/nss_memio.h',
'base/openssl_memory_private_key_store.cc', 'base/openssl_memory_private_key_store.cc',
'base/openssl_private_key_store.h', 'base/openssl_private_key_store.h',
'base/openssl_private_key_store_android.cc',
'base/origin_bound_cert_service.cc', 'base/origin_bound_cert_service.cc',
'base/origin_bound_cert_service.h', 'base/origin_bound_cert_service.h',
'base/origin_bound_cert_store.h', 'base/origin_bound_cert_store.h',
...@@ -935,6 +938,14 @@ ...@@ -935,6 +938,14 @@
# Android can shut down our app at any time, so we persist session cookies. # Android can shut down our app at any time, so we persist session cookies.
'ENABLE_PERSISTENT_SESSION_COOKIES' 'ENABLE_PERSISTENT_SESSION_COOKIES'
], ],
'dependencies': [
'../build/android/system.gyp:ssl',
],
'sources/': [
# TODO(jingzhao): The below files are excluded because of the
# missing JNI, add them back when JNI is ready.
['exclude', '^android/'],
],
}, { # else OS! = "android" }, { # else OS! = "android"
'defines': [ 'defines': [
# These are the features Android doesn't support. # These are the features Android doesn't support.
...@@ -951,6 +962,13 @@ ...@@ -951,6 +962,13 @@
}, },
], ],
], ],
'target_conditions': [
['OS == "android"', {
'sources/': [
['include', '^base/platform_mime_util_linux\\.cc$'],
],
}],
],
}, },
{ {
'target_name': 'net_unittests', 'target_name': 'net_unittests',
...@@ -1179,7 +1197,7 @@ ...@@ -1179,7 +1197,7 @@
], ],
}, },
], ],
[ 'os_posix == 1 and OS != "mac"', { [ 'os_posix == 1 and OS != "mac" and OS != "android"', {
'conditions': [ 'conditions': [
['linux_use_tcmalloc==1', { ['linux_use_tcmalloc==1', {
'dependencies': [ 'dependencies': [
...@@ -1245,6 +1263,15 @@ ...@@ -1245,6 +1263,15 @@
], ],
}, },
], ],
[ 'OS == "android"', {
'dependencies': [
'../build/android/system.gyp:ssl',
],
'sources!': [
'dns/dns_config_service_posix_unittest.cc',
],
},
],
], ],
}, },
{ {
...@@ -1381,7 +1408,7 @@ ...@@ -1381,7 +1408,7 @@
'../third_party/protobuf/protobuf.gyp:py_proto', '../third_party/protobuf/protobuf.gyp:py_proto',
], ],
}], }],
['os_posix == 1 and OS != "mac"', { ['os_posix == 1 and OS != "mac" and OS != "android"', {
'conditions': [ 'conditions': [
['use_openssl==1', { ['use_openssl==1', {
'dependencies': [ 'dependencies': [
...@@ -1394,7 +1421,7 @@ ...@@ -1394,7 +1421,7 @@
}], }],
], ],
}], }],
['os_posix == 1 and OS != "mac"', { ['os_posix == 1 and OS != "mac" and OS != "android"', {
'conditions': [ 'conditions': [
['linux_use_tcmalloc==1', { ['linux_use_tcmalloc==1', {
'dependencies': [ 'dependencies': [
...@@ -1510,7 +1537,7 @@ ...@@ -1510,7 +1537,7 @@
}, },
], ],
'conditions': [ 'conditions': [
['os_posix == 1 and OS != "mac"', { ['os_posix == 1 and OS != "mac" and OS != "android"', {
'targets': [ 'targets': [
{ {
'target_name': 'flip_in_mem_edsm_server', 'target_name': 'flip_in_mem_edsm_server',
......
...@@ -786,6 +786,10 @@ int SSLClientSocketOpenSSL::DoHandshake() { ...@@ -786,6 +786,10 @@ int SSLClientSocketOpenSSL::DoHandshake() {
return net_error; return net_error;
} }
// SelectNextProtoCallback is called by OpenSSL during the handshake. If the
// server supports NPN, selects a protocol from the list that the server
// provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the
// callback can assume that |in| is syntactically valid.
int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
unsigned char* outlen, unsigned char* outlen,
const unsigned char* in, const unsigned char* in,
...@@ -798,16 +802,31 @@ int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, ...@@ -798,16 +802,31 @@ int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out,
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
int status = SSL_select_next_proto( // Assume there's no overlap between our protocols and the server's list.
out, outlen, in, inlen, int status = OPENSSL_NPN_NO_OVERLAP;
reinterpret_cast<const unsigned char*>(ssl_config_.next_protos.data()), *out = const_cast<unsigned char*>(in) + 1;
ssl_config_.next_protos.size()); *outlen = in[0];
// For each protocol in server preference order, see if we support it.
for (unsigned int i = 0; i < inlen; i += in[i] + 1) {
for (std::vector<std::string>::const_iterator
j = ssl_config_.next_protos.begin();
j != ssl_config_.next_protos.end(); ++j) {
if (in[i] == j->size() &&
memcmp(&in[i + 1], j->data(), in[i]) == 0) {
// We find a match.
*out = const_cast<unsigned char*>(in) + i + 1;
*outlen = in[i];
status = OPENSSL_NPN_NEGOTIATED;
break;
}
}
if (status == OPENSSL_NPN_NEGOTIATED)
break;
}
npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen);
switch (status) { switch (status) {
case OPENSSL_NPN_UNSUPPORTED:
npn_status_ = SSLClientSocket::kNextProtoUnsupported;
break;
case OPENSSL_NPN_NEGOTIATED: case OPENSSL_NPN_NEGOTIATED:
npn_status_ = SSLClientSocket::kNextProtoNegotiated; npn_status_ = SSLClientSocket::kNextProtoNegotiated;
break; break;
......
...@@ -238,7 +238,7 @@ TEST(SpdyProtocolDeathTest, TestDataFrame) { ...@@ -238,7 +238,7 @@ TEST(SpdyProtocolDeathTest, TestDataFrame) {
frame.set_stream_id(0); frame.set_stream_id(0);
// TODO(mbelshe): implement EXPECT_DEBUG_DEATH on windows. // TODO(mbelshe): implement EXPECT_DEBUG_DEATH on windows.
#ifndef WIN32 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
#if !defined(DCHECK_ALWAYS_ON) #if !defined(DCHECK_ALWAYS_ON)
EXPECT_DEBUG_DEATH(frame.set_stream_id(~0), ""); EXPECT_DEBUG_DEATH(frame.set_stream_id(~0), "");
#else #else
...@@ -248,7 +248,7 @@ TEST(SpdyProtocolDeathTest, TestDataFrame) { ...@@ -248,7 +248,7 @@ TEST(SpdyProtocolDeathTest, TestDataFrame) {
EXPECT_FALSE(frame.is_control_frame()); EXPECT_FALSE(frame.is_control_frame());
frame.set_flags(0); frame.set_flags(0);
#ifndef WIN32 #if !defined(WIN32) && defined(GTEST_HAS_DEATH_TEST)
#if !defined(DCHECK_ALWAYS_ON) #if !defined(DCHECK_ALWAYS_ON)
EXPECT_DEBUG_DEATH(frame.set_length(~0), ""); EXPECT_DEBUG_DEATH(frame.set_length(~0), "");
#else #else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment