This source file includes following definitions.
- OnURLFetchComplete
- OnURLFetchDownloadProgress
- OnURLFetchUploadProgress
- OnAddEntry
- BuildURLRequestContext
- main_task_runner_
- GetURLRequestContext
- GetNetworkTaskRunner
- EstimateServerTimeNow
- EstimateSkew
- main
#include <cstdio>
#include <cstdlib>
#include <string>
#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/format_macros.h"
#include "base/i18n/time_formatting.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "net/base/net_errors.h"
#include "net/base/net_log.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_status.h"
#include "url/gurl.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
#elif defined(OS_LINUX)
#include "net/proxy/proxy_config.h"
#include "net/proxy/proxy_config_service_fixed.h"
#endif
using base::UTF16ToUTF8;
namespace {
const int64 kTicksResolutionMs = 15;
const int64 kServerTimeResolutionMs = 1000;
const int64 kTimeResolutionMs = kTicksResolutionMs;
class QuitDelegate : public net::URLFetcherDelegate {
public:
QuitDelegate() {}
virtual ~QuitDelegate() {}
virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
base::MessageLoop::current()->Quit();
}
virtual void OnURLFetchDownloadProgress(
const net::URLFetcher* source,
int64 current, int64 total) OVERRIDE {
NOTREACHED();
}
virtual void OnURLFetchUploadProgress(const net::URLFetcher* source,
int64 current, int64 total) OVERRIDE {
NOTREACHED();
}
private:
DISALLOW_COPY_AND_ASSIGN(QuitDelegate);
};
class PrintingLogObserver : public net::NetLog::ThreadSafeObserver {
public:
PrintingLogObserver() {}
virtual ~PrintingLogObserver() {
net_log()->RemoveThreadSafeObserver(this);
}
virtual void OnAddEntry(const net::NetLog::Entry& entry) OVERRIDE {
if (!VLOG_IS_ON(1))
return;
const char* const source_type =
net::NetLog::SourceTypeToString(entry.source().type);
const char* const event_type =
net::NetLog::EventTypeToString(entry.type());
const char* const event_phase =
net::NetLog::EventPhaseToString(entry.phase());
scoped_ptr<base::Value> params(entry.ParametersToValue());
std::string params_str;
if (params.get()) {
base::JSONWriter::Write(params.get(), ¶ms_str);
params_str.insert(0, ": ");
}
VLOG(1) << source_type << "(" << entry.source().id << "): "
<< event_type << ": " << event_phase << params_str;
}
private:
DISALLOW_COPY_AND_ASSIGN(PrintingLogObserver);
};
scoped_ptr<net::URLRequestContext>
BuildURLRequestContext(net::NetLog* net_log) {
net::URLRequestContextBuilder builder;
#if defined(OS_LINUX)
builder.set_proxy_config_service(
new net::ProxyConfigServiceFixed(net::ProxyConfig()));
#endif
scoped_ptr<net::URLRequestContext> context(builder.Build());
context->set_net_log(net_log);
return context.Pass();
}
class SingleThreadRequestContextGetter : public net::URLRequestContextGetter {
public:
SingleThreadRequestContextGetter(
net::NetLog* net_log,
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
: context_(BuildURLRequestContext(net_log)),
main_task_runner_(main_task_runner) {}
virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
return context_.get();
}
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetNetworkTaskRunner() const OVERRIDE {
return main_task_runner_;
}
private:
virtual ~SingleThreadRequestContextGetter() {}
const scoped_ptr<net::URLRequestContext> context_;
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
};
void EstimateServerTimeNow(base::Time server_time,
base::TimeTicks start_ticks,
base::TimeTicks end_ticks,
base::Time* server_now,
base::TimeDelta* server_now_uncertainty) {
const base::TimeDelta delta_ticks = end_ticks - start_ticks;
const base::TimeTicks mid_ticks = start_ticks + delta_ticks / 2;
const base::TimeDelta estimated_elapsed = base::TimeTicks::Now() - mid_ticks;
*server_now = server_time + estimated_elapsed;
*server_now_uncertainty =
base::TimeDelta::FromMilliseconds(kServerTimeResolutionMs) +
delta_ticks + 3 * base::TimeDelta::FromMilliseconds(kTicksResolutionMs);
}
void EstimateSkew(base::Time server_now,
base::TimeDelta server_now_uncertainty,
base::Time now,
base::TimeDelta now_uncertainty,
base::TimeDelta* skew,
base::TimeDelta* skew_uncertainty) {
*skew = server_now - now;
*skew_uncertainty = server_now_uncertainty + now_uncertainty;
}
}
int main(int argc, char* argv[]) {
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool pool;
#endif
base::AtExitManager exit_manager;
CommandLine::Init(argc, argv);
logging::LoggingSettings settings;
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
logging::InitLogging(settings);
const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
GURL url(parsed_command_line.GetSwitchValueASCII("url"));
if (!url.is_valid() ||
(url.scheme() != "http" && url.scheme() != "https")) {
std::fprintf(
stderr,
"Usage: %s --url=[http|https]://www.example.com [--v=[1|2]]\n",
argv[0]);
return EXIT_FAILURE;
}
base::MessageLoopForIO main_loop;
net::NetLog net_log;
PrintingLogObserver printing_log_observer;
net_log.AddThreadSafeObserver(&printing_log_observer, net::NetLog::LOG_ALL);
scoped_refptr<SingleThreadRequestContextGetter> context_getter(
new SingleThreadRequestContextGetter(&net_log,
main_loop.message_loop_proxy()));
QuitDelegate delegate;
scoped_ptr<net::URLFetcher> fetcher(
net::URLFetcher::Create(url, net::URLFetcher::HEAD, &delegate));
fetcher->SetRequestContext(context_getter.get());
const base::Time start_time = base::Time::Now();
const base::TimeTicks start_ticks = base::TimeTicks::Now();
fetcher->Start();
std::printf(
"Request started at %s (ticks = %" PRId64 ")\n",
UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(start_time)).c_str(),
start_ticks.ToInternalValue());
main_loop.Run();
const base::Time end_time = base::Time::Now();
const base::TimeTicks end_ticks = base::TimeTicks::Now();
std::printf(
"Request ended at %s (ticks = %" PRId64 ")\n",
UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(end_time)).c_str(),
end_ticks.ToInternalValue());
const int64 delta_ticks_internal =
end_ticks.ToInternalValue() - start_ticks.ToInternalValue();
const base::TimeDelta delta_ticks = end_ticks - start_ticks;
std::printf(
"Request took %" PRId64 " ticks (%.2f ms)\n",
delta_ticks_internal, delta_ticks.InMillisecondsF());
const net::URLRequestStatus status = fetcher->GetStatus();
if (status.status() != net::URLRequestStatus::SUCCESS) {
LOG(ERROR) << "Request failed with error code: "
<< net::ErrorToString(status.error());
return EXIT_FAILURE;
}
const net::HttpResponseHeaders* const headers =
fetcher->GetResponseHeaders();
if (!headers) {
LOG(ERROR) << "Response does not have any headers";
return EXIT_FAILURE;
}
void* iter = NULL;
std::string date_header;
while (headers->EnumerateHeader(&iter, "Date", &date_header)) {
std::printf("Got date header: %s\n", date_header.c_str());
}
base::Time server_time;
if (!headers->GetDateValue(&server_time)) {
LOG(ERROR) << "Could not parse time from server response headers";
return EXIT_FAILURE;
}
std::printf(
"Got time %s from server\n",
UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(server_time)).c_str());
base::Time server_now;
base::TimeDelta server_now_uncertainty;
EstimateServerTimeNow(server_time, start_ticks, end_ticks,
&server_now, &server_now_uncertainty);
base::Time now = base::Time::Now();
std::printf(
"According to the server, it is now %s with uncertainty %.2f ms\n",
UTF16ToUTF8(base::TimeFormatFriendlyDateAndTime(server_now)).c_str(),
server_now_uncertainty.InMillisecondsF());
base::TimeDelta skew;
base::TimeDelta skew_uncertainty;
EstimateSkew(server_now, server_now_uncertainty, now,
base::TimeDelta::FromMilliseconds(kTimeResolutionMs),
&skew, &skew_uncertainty);
std::printf(
"An estimate for the local clock skew is %.2f ms with "
"uncertainty %.2f ms\n",
skew.InMillisecondsF(),
skew_uncertainty.InMillisecondsF());
return EXIT_SUCCESS;
}