10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2011, Google Inc. 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define WIN32_LEAN_AND_MEAN 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <windows.h> 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define snprintf _snprintf 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#undef ERROR // wingdi.h 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef OSX 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <CoreServices/CoreServices.h> 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#elif defined(ANDROID) 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <android/log.h> 390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const char kLibjingle[] = "libjingle"; 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Android has a 1024 limit on log inputs. We use 60 chars as an 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// approx for the header/tag portion. 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// See android/system/core/liblog/logd_write.c 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kMaxLogLineSize = 1024 - 60; 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // OSX || ANDROID 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <time.h> 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <ostream> 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <iomanip> 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <limits.h> 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <vector> 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/logging.h" 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/stream.h" 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/stringencode.h" 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/stringutils.h" 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/base/timeutils.h" 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace talk_base { 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Constant Labels 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char * FindLabel(int value, const ConstantLabel entries[]) { 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (int i = 0; entries[i].label; ++i) { 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (value == entries[i].value) { 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return entries[i].label; 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return 0; 720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string ErrorName(int err, const ConstantLabel * err_table) { 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (err == 0) 760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return "No error"; 770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (err_table != 0) { 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (const char * value = FindLabel(err, err_table)) 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return value; 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char buffer[16]; 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org snprintf(buffer, sizeof(buffer), "0x%08x", err); 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return buffer; 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// LogMessage 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////////////// 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int LogMessage::NO_LOGGING = LS_ERROR + 1; 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if _DEBUG 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int LOG_DEFAULT = LS_INFO; 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else // !_DEBUG 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int LOG_DEFAULT = LogMessage::NO_LOGGING; 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // !_DEBUG 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Global lock for log subsystem, only needed to serialize access to streams_. 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCriticalSection LogMessage::crit_; 1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// By default, release builds don't log, debug builds at info level 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint LogMessage::min_sev_ = LOG_DEFAULT; 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint LogMessage::dbg_sev_ = LOG_DEFAULT; 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Don't bother printing context for the ubiquitous INFO log messages 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint LogMessage::ctx_sev_ = LS_WARNING; 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// The list of logging streams currently configured. 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Note: we explicitly do not clean this up, because of the uncertain ordering 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// of destructors at program exit. Let the person who sets the stream trigger 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// cleanup by setting to NULL, or let it leak (safe at program exit). 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgLogMessage::StreamList LogMessage::streams_; 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Boolean options default to false (0) 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool LogMessage::thread_, LogMessage::timestamp_; 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// If we're in diagnostic mode, we'll be explicitly set that way; default=false. 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool LogMessage::is_diagnostic_mode_ = false; 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgLogMessage::LogMessage(const char* file, int line, LoggingSeverity sev, 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogErrorContext err_ctx, int err, const char* module) 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : severity_(sev), 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org warn_slow_logs_delay_(WARN_SLOW_LOGS_DELAY) { 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (timestamp_) { 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 time = TimeSince(LogStartTime()); 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Also ensure WallClockStartTime is initialized, so that it matches 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // LogStartTime. 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org WallClockStartTime(); 1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org print_stream_ << "[" << std::setfill('0') << std::setw(3) << (time / 1000) 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ":" << std::setw(3) << (time % 1000) << std::setfill(' ') 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "] "; 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (thread_) { 1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DWORD id = GetCurrentThreadId(); 1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org print_stream_ << "[" << std::hex << id << std::dec << "] "; 1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // WIN32 1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (severity_ >= ctx_sev_) { 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org print_stream_ << Describe(sev) << "(" << DescribeFile(file) 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ":" << line << "): "; 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (err_ctx != ERRCTX_NONE) { 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::ostringstream tmp; 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tmp << "[0x" << std::setfill('0') << std::hex << std::setw(8) << err << "]"; 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (err_ctx) { 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case ERRCTX_ERRNO: 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tmp << " " << strerror(err); 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if WIN32 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case ERRCTX_HRESULT: { 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char msgbuf[256]; 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM; 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org HMODULE hmod = GetModuleHandleA(module); 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (hmod) 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org flags |= FORMAT_MESSAGE_FROM_HMODULE; 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (DWORD len = FormatMessageA( 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org flags, hmod, err, 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org msgbuf, sizeof(msgbuf) / sizeof(msgbuf[0]), NULL)) { 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while ((len > 0) && 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org isspace(static_cast<unsigned char>(msgbuf[len-1]))) { 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org msgbuf[--len] = 0; 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tmp << " " << msgbuf; 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // WIN32 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if OSX 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case ERRCTX_OSSTATUS: { 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tmp << " " << nonnull(GetMacOSStatusErrorString(err), "Unknown error"); 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (const char* desc = GetMacOSStatusCommentString(err)) { 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tmp << ": " << desc; 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // OSX 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org extra_ = tmp.str(); 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgLogMessage::~LogMessage() { 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!extra_.empty()) 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org print_stream_ << " : " << extra_; 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org print_stream_ << std::endl; 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& str = print_stream_.str(); 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (severity_ >= dbg_sev_) { 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OutputToDebug(str, severity_); 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 before = Time(); 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Must lock streams_ before accessing 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CritScope cs(&crit_); 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (severity_ >= it->second) { 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OutputToStream(it->first, str); 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 delay = TimeSince(before); 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (delay >= warn_slow_logs_delay_) { 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogMessage slow_log_warning = 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org talk_base::LogMessage(__FILE__, __LINE__, LS_WARNING); 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If our warning is slow, we don't want to warn about it, because 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // that would lead to inifinite recursion. So, give a really big 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // number for the delay threshold. 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org slow_log_warning.warn_slow_logs_delay_ = UINT_MAX; 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org slow_log_warning.stream() << "Slow log: took " << delay << "ms to write " 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << str.size() << " bytes."; 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 LogMessage::LogStartTime() { 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const uint32 g_start = Time(); 2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return g_start; 2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orguint32 LogMessage::WallClockStartTime() { 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const uint32 g_start_wallclock = time(NULL); 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return g_start_wallclock; 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::LogContext(int min_sev) { 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ctx_sev_ = min_sev; 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::LogThreads(bool on) { 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org thread_ = on; 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::LogTimestamps(bool on) { 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org timestamp_ = on; 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::LogToDebug(int min_sev) { 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org dbg_sev_ = min_sev; 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateMinLogSeverity(); 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::LogToStream(StreamInterface* stream, int min_sev) { 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CritScope cs(&crit_); 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Discard and delete all previously installed streams 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delete it->first; 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org streams_.clear(); 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Install the new stream, if specified 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (stream) { 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org AddLogToStream(stream, min_sev); 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint LogMessage::GetLogToStream(StreamInterface* stream) { 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CritScope cs(&crit_); 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int sev = NO_LOGGING; 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!stream || stream == it->first) { 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org sev = _min(sev, it->second); 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return sev; 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::AddLogToStream(StreamInterface* stream, int min_sev) { 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CritScope cs(&crit_); 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org streams_.push_back(std::make_pair(stream, min_sev)); 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateMinLogSeverity(); 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::RemoveLogToStream(StreamInterface* stream) { 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CritScope cs(&crit_); 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (stream == it->first) { 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org streams_.erase(it); 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateMinLogSeverity(); 2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::ConfigureLogging(const char* params, const char* filename) { 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int current_level = LS_VERBOSE; 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int debug_level = GetLogToDebug(); 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int file_level = GetLogToStream(); 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<std::string> tokens; 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org tokenize(params, ' ', &tokens); 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (size_t i = 0; i < tokens.size(); ++i) { 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (tokens[i].empty()) 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org continue; 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Logging features 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (tokens[i] == "tstamp") { 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogTimestamps(); 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "thread") { 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogThreads(); 3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Logging levels 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "sensitive") { 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org current_level = LS_SENSITIVE; 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "verbose") { 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org current_level = LS_VERBOSE; 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "info") { 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org current_level = LS_INFO; 3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "warning") { 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org current_level = LS_WARNING; 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "error") { 3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org current_level = LS_ERROR; 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "none") { 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org current_level = NO_LOGGING; 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Logging targets 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "file") { 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org file_level = current_level; 3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (tokens[i] == "debug") { 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org debug_level = current_level; 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if ((NO_LOGGING != debug_level) && !::IsDebuggerPresent()) { 3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // First, attempt to attach to our parent's console... so if you invoke 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // from the command line, we'll see the output there. Otherwise, create 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // our own console window. 3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note: These methods fail if a console already exists, which is fine. 3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool success = false; 3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org typedef BOOL (WINAPI* PFN_AttachConsole)(DWORD); 3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (HINSTANCE kernel32 = ::LoadLibrary(L"kernel32.dll")) { 3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // AttachConsole is defined on WinXP+. 3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (PFN_AttachConsole attach_console = reinterpret_cast<PFN_AttachConsole> 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (::GetProcAddress(kernel32, "AttachConsole"))) { 3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org success = (FALSE != attach_console(ATTACH_PARENT_PROCESS)); 3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ::FreeLibrary(kernel32); 3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!success) { 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ::AllocConsole(); 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // WIN32 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3528485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org LogToDebug(debug_level); 3538485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org 3548485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org#if !defined(__native_client__) // No logging to file in NaCl. 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org scoped_ptr<FileStream> stream; 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (NO_LOGGING != file_level) { 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream.reset(new FileStream); 3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!stream->Open(filename, "wb", NULL) || !stream->DisableBuffering()) { 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream.reset(); 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogToStream(stream.release(), file_level); 3648485ec698cd13d65354e2f81132b5763a3d216a4henrika@webrtc.org#endif 3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint LogMessage::ParseLogSeverity(const std::string& value) { 3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int level = NO_LOGGING; 3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (value == "LS_SENSITIVE") { 3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org level = LS_SENSITIVE; 3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (value == "LS_VERBOSE") { 3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org level = LS_VERBOSE; 3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (value == "LS_INFO") { 3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org level = LS_INFO; 3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (value == "LS_WARNING") { 3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org level = LS_WARNING; 3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (value == "LS_ERROR") { 3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org level = LS_ERROR; 3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (isdigit(value[0])) { 3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org level = atoi(value.c_str()); // NOLINT 3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return level; 3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::UpdateMinLogSeverity() { 3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int min_sev = dbg_sev_; 3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (StreamList::iterator it = streams_.begin(); it != streams_.end(); ++it) { 3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org min_sev = _min(dbg_sev_, it->second); 3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org min_sev_ = min_sev; 3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* LogMessage::Describe(LoggingSeverity sev) { 3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (sev) { 3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_SENSITIVE: return "Sensitive"; 3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_VERBOSE: return "Verbose"; 3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_INFO: return "Info"; 3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_WARNING: return "Warning"; 3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_ERROR: return "Error"; 4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: return "<unknown>"; 4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst char* LogMessage::DescribeFile(const char* file) { 4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char* end1 = ::strrchr(file, '/'); 4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char* end2 = ::strrchr(file, '\\'); 4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!end1 && !end2) 4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return file; 4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org else 4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (end1 > end2) ? end1 + 1 : end2 + 1; 4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::OutputToDebug(const std::string& str, 4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LoggingSeverity severity) { 4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool log_to_stderr = true; 4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if defined(OSX) && (!defined(DEBUG) || defined(NDEBUG)) 4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // On the Mac, all stderr output goes to the Console log and causes clutter. 4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // So in opt builds, don't log to stderr unless the user specifically sets 4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // a preference to do so. 4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CFStringRef key = CFStringCreateWithCString(kCFAllocatorDefault, 4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org "logToStdErr", 4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org kCFStringEncodingUTF8); 4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CFStringRef domain = CFBundleGetIdentifier(CFBundleGetMainBundle()); 4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (key != NULL && domain != NULL) { 4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Boolean exists_and_is_valid; 4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Boolean should_log = 4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CFPreferencesGetAppBooleanValue(key, domain, &exists_and_is_valid); 4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If the key doesn't exist or is invalid or is false, we will not log to 4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // stderr. 4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org log_to_stderr = exists_and_is_valid && should_log; 4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (key != NULL) { 4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CFRelease(key); 4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef WIN32 4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Always log to the debugger. 4380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Perhaps stderr should be controlled by a preference, as on Mac? 4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org OutputDebugStringA(str.c_str()); 4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (log_to_stderr) { 4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // This handles dynamically allocated consoles, too. 4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (HANDLE error_handle = ::GetStdHandle(STD_ERROR_HANDLE)) { 4430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org log_to_stderr = false; 4440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org DWORD written = 0; 4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ::WriteFile(error_handle, str.data(), static_cast<DWORD>(str.size()), 4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &written, 0); 4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // WIN32 4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef ANDROID 4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Android's logging facility uses severity to log messages but we 4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // need to map libjingle's severity levels to Android ones first. 4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Also write to stderr which maybe available to executable started 4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // from the shell. 4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int prio; 4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (severity) { 4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_SENSITIVE: 4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org __android_log_write(ANDROID_LOG_INFO, kLibjingle, "SENSITIVE"); 4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (log_to_stderr) { 4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org fprintf(stderr, "SENSITIVE"); 4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org fflush(stderr); 4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_VERBOSE: 4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org prio = ANDROID_LOG_VERBOSE; 4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_INFO: 4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org prio = ANDROID_LOG_INFO; 4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_WARNING: 4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org prio = ANDROID_LOG_WARN; 4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case LS_ERROR: 4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org prio = ANDROID_LOG_ERROR; 4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org prio = ANDROID_LOG_UNKNOWN; 4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int size = str.size(); 4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int line = 0; 4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int idx = 0; 4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const int max_lines = size / kMaxLogLineSize + 1; 4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (max_lines == 1) { 4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org __android_log_print(prio, kLibjingle, "%.*s", size, str.c_str()); 4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (size > 0) { 4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const int len = std::min(size, kMaxLogLineSize); 4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Use the size of the string in the format (str may have \0 in the 4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // middle). 4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org __android_log_print(prio, kLibjingle, "[%d/%d] %.*s", 4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org line + 1, max_lines, 4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org len, str.c_str() + idx); 4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org idx += len; 4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size -= len; 4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ++line; 4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // ANDROID 5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (log_to_stderr) { 5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org fprintf(stderr, "%s", str.c_str()); 5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org fflush(stderr); 5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMessage::OutputToStream(StreamInterface* stream, 5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& str) { 5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If write isn't fully successful, what are we going to do, log it? :) 5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org stream->WriteAll(str.data(), str.size(), NULL, NULL); 5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Logging Helpers 5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid LogMultiline(LoggingSeverity level, const char* label, bool input, 5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const void* data, size_t len, bool hex_mode, 5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LogMultilineState* state) { 5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!LOG_CHECK_LEVEL_V(level)) 5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const char * direction = (input ? " << " : " >> "); 5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // NULL data means to flush our count of unprintable characters. 5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!data) { 5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (state && state->unprintable_count_[input]) { 5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(level) << label << direction << "## " 5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << state->unprintable_count_[input] 5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " consecutive unprintable ##"; 5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org state->unprintable_count_[input] = 0; 5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The ctype classification functions want unsigned chars. 5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const unsigned char* udata = static_cast<const unsigned char*>(data); 5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (hex_mode) { 5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const size_t LINE_SIZE = 24; 5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org char hex_line[LINE_SIZE * 9 / 4 + 2], asc_line[LINE_SIZE + 1]; 5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (len > 0) { 5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org memset(asc_line, ' ', sizeof(asc_line)); 5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org memset(hex_line, ' ', sizeof(hex_line)); 5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t line_len = _min(len, LINE_SIZE); 5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (size_t i = 0; i < line_len; ++i) { 5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org unsigned char ch = udata[i]; 5470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org asc_line[i] = isprint(ch) ? ch : '.'; 5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org hex_line[i*2 + i/4] = hex_encode(ch >> 4); 5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org hex_line[i*2 + i/4 + 1] = hex_encode(ch & 0xf); 5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org asc_line[sizeof(asc_line)-1] = 0; 5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org hex_line[sizeof(hex_line)-1] = 0; 5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(level) << label << direction 5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << asc_line << " " << hex_line << " "; 5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org udata += line_len; 5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org len -= line_len; 5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t consecutive_unprintable = state ? state->unprintable_count_[input] : 0; 5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const unsigned char* end = udata + len; 5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (udata < end) { 5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const unsigned char* line = udata; 5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const unsigned char* end_of_line = strchrn<unsigned char>(udata, 5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org end - udata, 5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org '\n'); 5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!end_of_line) { 5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org udata = end_of_line = end; 5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org udata = end_of_line + 1; 5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_printable = true; 5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If we are in unprintable mode, we need to see a line of at least 5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // kMinPrintableLine characters before we'll switch back. 5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const ptrdiff_t kMinPrintableLine = 4; 5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (consecutive_unprintable && ((end_of_line - line) < kMinPrintableLine)) { 5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_printable = false; 5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Determine if the line contains only whitespace and printable 5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // characters. 5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_entirely_whitespace = true; 5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (const unsigned char* pos = line; pos < end_of_line; ++pos) { 5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (isspace(*pos)) 5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org continue; 5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_entirely_whitespace = false; 5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!isprint(*pos)) { 5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_printable = false; 5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Treat an empty line following unprintable data as unprintable. 5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (consecutive_unprintable && is_entirely_whitespace) { 5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org is_printable = false; 5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!is_printable) { 6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org consecutive_unprintable += (udata - line); 6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org continue; 6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Print out the current line, but prefix with a count of prior unprintable 6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // characters. 6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (consecutive_unprintable) { 6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(level) << label << direction << "## " << consecutive_unprintable 6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << " consecutive unprintable ##"; 6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org consecutive_unprintable = 0; 6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Strip off trailing whitespace. 6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while ((end_of_line > line) && isspace(*(end_of_line-1))) { 6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org --end_of_line; 6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Filter out any private data 6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string substr(reinterpret_cast<const char*>(line), end_of_line - line); 6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string::size_type pos_private = substr.find("Email"); 6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (pos_private == std::string::npos) { 6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org pos_private = substr.find("Passwd"); 6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (pos_private == std::string::npos) { 6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(level) << label << direction << substr; 6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG_V(level) << label << direction << "## omitted for privacy ##"; 6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (state) { 6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org state->unprintable_count_[input] = consecutive_unprintable; 6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org////////////////////////////////////////////////////////////////////// 6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace talk_base 636