1c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 2c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Copyright (C) 2013 The Android Open Source Project 3c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 4c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Licensed under the Apache License, Version 2.0 (the "License"); 5c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// you may not use this file except in compliance with the License. 6c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// You may obtain a copy of the License at 7c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 8c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// http://www.apache.org/licenses/LICENSE-2.0 9c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 10c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// Unless required by applicable law or agreed to in writing, software 11c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// distributed under the License is distributed on an "AS IS" BASIS, 12c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// See the License for the specific language governing permissions and 14c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// limitations under the License. 15c0beca55d290fe0b1c96d78cbbcf94b05c23f5a5Peter Qiu// 163e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 173e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan#include "shill/socket_info_reader.h" 183e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 193e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan#include <algorithm> 203e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan#include <limits> 213e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 22a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_number_conversions.h> 23a0ddf46e466bd4ba3d20952f0a6988c680c1af14Ben Chan#include <base/strings/string_split.h> 243a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko#include <base/strings/string_util.h> 253e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 263e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan#include "shill/file_reader.h" 273e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan#include "shill/logging.h" 283e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 293e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanusing base::FilePath; 303e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanusing std::string; 313e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanusing std::vector; 323e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 333e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Channamespace shill { 343e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 35c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinnamespace Logging { 36c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silbersteinstatic auto kModuleLogScope = ScopeLogger::kLink; 371a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartstatic string ObjectID(SocketInfoReader* s) { return "(socket_info_reader)"; } 38c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein} 39c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein 403e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Channamespace { 413e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 42320d04a93dcde82899b4457351d00aad4528e4c9Ben Chanconst char kTcpv4SocketInfoFilePath[] = "/proc/net/tcp"; 43320d04a93dcde82899b4457351d00aad4528e4c9Ben Chanconst char kTcpv6SocketInfoFilePath[] = "/proc/net/tcp6"; 443e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 453e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} // namespace 463e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 473e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben ChanSocketInfoReader::SocketInfoReader() {} 483e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 493e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben ChanSocketInfoReader::~SocketInfoReader() {} 503e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 51320d04a93dcde82899b4457351d00aad4528e4c9Ben ChanFilePath SocketInfoReader::GetTcpv4SocketInfoFilePath() const { 52320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan return FilePath(kTcpv4SocketInfoFilePath); 53320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan} 54320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan 55320d04a93dcde82899b4457351d00aad4528e4c9Ben ChanFilePath SocketInfoReader::GetTcpv6SocketInfoFilePath() const { 56320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan return FilePath(kTcpv6SocketInfoFilePath); 57320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan} 58320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan 591a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool SocketInfoReader::LoadTcpSocketInfo(vector<SocketInfo>* info_list) { 60320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan info_list->clear(); 61320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan bool v4_loaded = AppendSocketInfo(GetTcpv4SocketInfoFilePath(), info_list); 62320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan bool v6_loaded = AppendSocketInfo(GetTcpv6SocketInfoFilePath(), info_list); 63320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan // Return true if we can load either /proc/net/tcp or /proc/net/tcp6 64320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan // successfully. 65320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan return v4_loaded || v6_loaded; 663e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 673e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 681a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool SocketInfoReader::AppendSocketInfo(const FilePath& info_file_path, 691a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart vector<SocketInfo>* info_list) { 703e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan FileReader file_reader; 713e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (!file_reader.Open(info_file_path)) { 72c9c31d8497c3f053c2160408cc386010fc125fadRebecca Silberstein SLOG(this, 2) << __func__ << ": Failed to open '" 733e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan << info_file_path.value() << "'."; 743e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 753e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 763e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 773e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan string line; 783e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan while (file_reader.ReadLine(&line)) { 793e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan SocketInfo socket_info; 803e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (ParseSocketInfo(line, &socket_info)) 813e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan info_list->push_back(socket_info); 823e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 833e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 843e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 853e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 861a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool SocketInfoReader::ParseSocketInfo(const string& input, 871a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart SocketInfo* socket_info) { 883a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko vector<string> tokens = base::SplitString(input, base::kWhitespaceASCII, 893a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::KEEP_WHITESPACE, 903a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko base::SPLIT_WANT_NONEMPTY); 913e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (tokens.size() < 10) { 923e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 933e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 943e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 953e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan IPAddress ip_address(IPAddress::kFamilyUnknown); 967fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint16_t port = 0; 973e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 983e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (!ParseIPAddressAndPort(tokens[1], &ip_address, &port)) { 993e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1003e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1013e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_local_ip_address(ip_address); 1023e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_local_port(port); 1033e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1043e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (!ParseIPAddressAndPort(tokens[2], &ip_address, &port)) { 1053e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1063e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1073e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_remote_ip_address(ip_address); 1083e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_remote_port(port); 1093e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1103e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan SocketInfo::ConnectionState connection_state = 1113e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan SocketInfo::kConnectionStateUnknown; 1123e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (!ParseConnectionState(tokens[3], &connection_state)) { 1133e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1143e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1153e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_connection_state(connection_state); 1163e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1177fab89734d88724a288e96a9996b15548c5294c7Ben Chan uint64_t transmit_queue_value = 0, receive_queue_value = 0; 1183e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (!ParseTransimitAndReceiveQueueValues( 1193e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan tokens[4], &transmit_queue_value, &receive_queue_value)) { 1203e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1213e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1223e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_transmit_queue_value(transmit_queue_value); 1233e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_receive_queue_value(receive_queue_value); 1243e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1253e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan SocketInfo::TimerState timer_state = SocketInfo::kTimerStateUnknown; 1263e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (!ParseTimerState(tokens[5], &timer_state)) { 1273e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1283e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1293e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan socket_info->set_timer_state(timer_state); 1303e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1313e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 1323e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 1333e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1343e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanbool SocketInfoReader::ParseIPAddressAndPort( 1351a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const string& input, IPAddress* ip_address, uint16_t* port) { 1363a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko vector<string> tokens = base::SplitString( 1373a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko input, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 1383e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (tokens.size() != 2 || 1393e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan !ParseIPAddress(tokens[0], ip_address) || 1403e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan !ParsePort(tokens[1], port)) { 1413e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1423e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1433e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1443e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 1453e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 1463e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1471a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool SocketInfoReader::ParseIPAddress(const string& input, 1481a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart IPAddress* ip_address) { 149320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan ByteString byte_string = ByteString::CreateFromHexString(input); 150320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan if (byte_string.IsEmpty()) 1513e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1523e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1533e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan IPAddress::Family family; 154320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan if (byte_string.GetLength() == 155320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan IPAddress::GetAddressLength(IPAddress::kFamilyIPv4)) { 1563e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan family = IPAddress::kFamilyIPv4; 157320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan } else if (byte_string.GetLength() == 158320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan IPAddress::GetAddressLength(IPAddress::kFamilyIPv6)) { 1593e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan family = IPAddress::kFamilyIPv6; 160320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan } else { 1613e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 162320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan } 1633e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 164320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan // Linux kernel prints out IP addresses in network order via 165320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan // /proc/net/tcp{,6}. 166320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan byte_string.ConvertFromNetToCPUUInt32Array(); 1673e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 168320d04a93dcde82899b4457351d00aad4528e4c9Ben Chan *ip_address = IPAddress(family, byte_string); 1693e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 1703e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 1713e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1721a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewartbool SocketInfoReader::ParsePort(const string& input, uint16_t* port) { 1733e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan int result = 0; 1743e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1753e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (input.size() != 4 || !base::HexStringToInt(input, &result) || 1767fab89734d88724a288e96a9996b15548c5294c7Ben Chan result < 0 || result > std::numeric_limits<uint16_t>::max()) { 1773e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1783e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1793e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1803e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan *port = result; 1813e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 1823e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 1833e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1843e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanbool SocketInfoReader::ParseTransimitAndReceiveQueueValues( 1851a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const string& input, 1861a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart uint64_t* transmit_queue_value, uint64_t* receive_queue_value) { 1877fab89734d88724a288e96a9996b15548c5294c7Ben Chan int64_t signed_transmit_queue_value = 0, signed_receive_queue_value = 0; 1883e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1893a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko vector<string> tokens = base::SplitString( 1903a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko input, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 1913e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (tokens.size() != 2 || 1923e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan !base::HexStringToInt64(tokens[0], &signed_transmit_queue_value) || 1933e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan !base::HexStringToInt64(tokens[1], &signed_receive_queue_value)) { 1943e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 1953e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 1963e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 1977fab89734d88724a288e96a9996b15548c5294c7Ben Chan *transmit_queue_value = static_cast<uint64_t>(signed_transmit_queue_value); 1987fab89734d88724a288e96a9996b15548c5294c7Ben Chan *receive_queue_value = static_cast<uint64_t>(signed_receive_queue_value); 1993e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 2003e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 2013e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2023e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanbool SocketInfoReader::ParseConnectionState( 2031a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const string& input, SocketInfo::ConnectionState* connection_state) { 2043e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan int result = 0; 2053e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2063e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (input.size() != 2 || !base::HexStringToInt(input, &result)) { 2073e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 2083e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 2093e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2103e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (result > 0 && result < SocketInfo::kConnectionStateMax) { 2113e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan *connection_state = static_cast<SocketInfo::ConnectionState>(result); 2123e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } else { 2133e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan *connection_state = SocketInfo::kConnectionStateUnknown; 2143e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 2153e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 2163e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 2173e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2183e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chanbool SocketInfoReader::ParseTimerState( 2191a212a6b98b22ad1d69652bb26a9e94138635476Paul Stewart const string& input, SocketInfo::TimerState* timer_state) { 2203e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan int result = 0; 2213e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2223a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko vector<string> tokens = base::SplitString( 2233a62e235646ec19bee71e8dbee5208282dcd13b5Alex Vakulenko input, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); 2243e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (tokens.size() != 2 || tokens[0].size() != 2 || 2253e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan !base::HexStringToInt(tokens[0], &result)) { 2263e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return false; 2273e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 2283e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2293e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan if (result < SocketInfo::kTimerStateMax) { 2303e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan *timer_state = static_cast<SocketInfo::TimerState>(result); 2313e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } else { 2323e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan *timer_state = SocketInfo::kTimerStateUnknown; 2333e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan } 2343e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan return true; 2353e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} 2363e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan 2373e4bf16679baaddd8ff149b7ca872e1ee12f57b7Ben Chan} // namespace shill 238