• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "network_plugin.h"
16 #include "buffer_splitter.h"
17 #include "securec.h"
18 
19 #include <string>
20 
21 namespace {
22 constexpr size_t READ_BUFFER_SIZE = 1024 * 16;
23 const std::string DEFAULT_NET_PATH("/proc/net/xt_qtaguid/stats");
24 } // namespace
25 
NetworkPlugin()26 NetworkPlugin::NetworkPlugin()
27     : buffer_(new (std::nothrow) uint8_t[READ_BUFFER_SIZE]), fp_(nullptr, nullptr)
28 {
29     pidUid_.clear();
30 }
31 
Start(const uint8_t * configData,uint32_t configSize)32 int NetworkPlugin::Start(const uint8_t* configData, uint32_t configSize)
33 {
34     CHECK_NOTNULL(buffer_, -1, "%s:NetworkPlugin, buffer_ is null", __func__);
35 
36     if (protoConfig_.ParseFromArray(configData, configSize) <= 0) {
37         HILOG_ERROR(LOG_CORE, "%s:NetworkPlugin, parseFromArray failed!", __func__);
38         return -1;
39     }
40 
41     for (int i = 0; i < protoConfig_.pid().size(); i++) {
42         int32_t pid = protoConfig_.pid(i);
43         pidUid_.emplace(pid, GetUid(pid));
44     }
45 
46     HILOG_INFO(LOG_CORE, "%s:NetworkPlugin, start success!", __func__);
47 
48     return 0;
49 }
50 
Report(uint8_t * data,uint32_t dataSize)51 int NetworkPlugin::Report(uint8_t* data, uint32_t dataSize)
52 {
53     NetworkDatas dataProto;
54     std::string file = GetRateNodePath();
55     char realPath[PATH_MAX + 1] = {0};
56 
57     if ((file.length() > PATH_MAX) || (realpath(file.c_str(), realPath) == nullptr)) {
58         return -1;
59     }
60     fp_ = std::unique_ptr<FILE, int (*)(FILE*)>(fopen(realPath, "r"), fclose);
61     CHECK_NOTNULL(fp_, -1, "%s:NetworkPlugin, open(%s) Failed, errno(%d)", __func__, file.c_str(), errno);
62 
63     for (int i = 0; i < protoConfig_.pid().size(); i++) {
64         auto* info = dataProto.add_networkinfo();
65         int32_t pid = protoConfig_.pid(i);
66         NetworkCell dataCell = {0};
67         ReadTxRxBytes(pid, dataCell);
68         // set proto
69         for (auto& it : dataCell.details) {
70             NetworkDetails* data = info->add_details();
71             data->set_tx_bytes(it.tx);
72             data->set_rx_bytes(it.rx);
73             data->set_type(it.type);
74         }
75         info->set_pid(pid);
76         info->set_tx_bytes(dataCell.tx);
77         info->set_rx_bytes(dataCell.rx);
78         info->set_tv_sec(dataCell.ts.tv_sec);
79         info->set_tv_nsec(dataCell.ts.tv_nsec);
80     }
81 
82     uint32_t length = dataProto.ByteSizeLong();
83     if (length > dataSize) {
84         return -length;
85     }
86     if (dataProto.SerializeToArray(data, length) > 0) {
87         return length;
88     }
89     return 0;
90 }
91 
Stop()92 int NetworkPlugin::Stop()
93 {
94     HILOG_INFO(LOG_CORE, "%s:NetworkPlugin, stop success!", __func__);
95     return 0;
96 }
97 
GetRateNodePath()98 std::string NetworkPlugin::GetRateNodePath()
99 {
100     std::string name = "";
101 
102     if (!fileForTest_.empty()) {
103         name = fileForTest_ + DEFAULT_NET_PATH;
104         return name;
105     }
106     if (access(DEFAULT_NET_PATH.c_str(), F_OK) == 0) {
107         name = DEFAULT_NET_PATH;
108     }
109     return name;
110 }
111 
GetUid(int32_t pid)112 int32_t NetworkPlugin::GetUid(int32_t pid)
113 {
114     if (pid <= 0) {
115         HILOG_ERROR(LOG_CORE, "%s:NetworkPlugin, check param fail, pid less than 0!", __func__);
116         return -1;
117     }
118 
119     char* end = nullptr;
120     std::string path = std::string("/proc/") + std::to_string(pid) + std::string("/status");
121     if (!fileForTest_.empty()) {
122         path = fileForTest_ + std::string("/proc/") + std::to_string(pid) + std::string("/status");
123     }
124     std::ifstream input(path, std::ios::in);
125     if (input.fail()) {
126         const int bufSize = 1024;
127         char buf[bufSize] = { 0 };
128         strerror_r(errno, buf, bufSize);
129         HILOG_ERROR(LOG_CORE, "%s:NetworkPlugin, open %s failed, errno(%s)", __func__, path.c_str(), buf);
130         return -1;
131     }
132     do {
133         if (!input.good()) {
134             return -1;
135         }
136         std::string line;
137         getline(input, line);
138         if (!strncmp(line.c_str(), "Uid:", strlen("Uid:"))) {
139             std::string str = line.substr(strlen("Uid:\t"));
140             HILOG_INFO(LOG_CORE, "%s:NetworkPlugin, line(%s), str(%s)", __func__, line.c_str(), str.c_str());
141             return strtol(str.c_str(), &end, DEC_BASE);
142         }
143     } while (!input.eof());
144     input.close();
145 
146     return -1;
147 }
148 
ReadTxRxBytes(int32_t pid,NetworkCell & cell)149 bool NetworkPlugin::ReadTxRxBytes(int32_t pid, NetworkCell &cell)
150 {
151     int32_t uid = pidUid_.at(pid);
152     CHECK_NOTNULL(fp_.get(), false, "%s:NetworkPlugin, fp_ is null", __func__);
153     int ret = fseek(fp_.get(), 0, SEEK_SET);
154     CHECK_TRUE(ret == 0, false, "%s:NetworkPlugin, fseek failed, error(%d)!", __func__, errno);
155     size_t rsize = static_cast<size_t>(fread(buffer_.get(), sizeof(char), READ_BUFFER_SIZE - 1, fp_.get()));
156     buffer_.get()[rsize] = '\0';
157     CHECK_TRUE(rsize >= 0, false, "%s:NetworkPlugin, read failed, errno(%d)", __func__, errno);
158     char* end = nullptr;
159     BufferSplitter totalbuffer((const char*)buffer_.get(), rsize + 1);
160     do {
161         int index = 0;
162         NetDetails cache = {0};
163         char tmp[TX_INDEX + 1] = {0};
164         while (totalbuffer.NextWord(' ')) {
165             index++;
166             if (totalbuffer.CurWord() == nullptr) {
167                 continue;
168             }
169             if (index == IFACE_INDEX && !strncmp(totalbuffer.CurWord(), "lo", strlen("lo"))) {
170                 break;
171             }
172             if (index == IFACE_INDEX &&
173                 strncpy_s(tmp, sizeof(tmp), totalbuffer.CurWord(), totalbuffer.CurWordSize()) == EOK) {
174                 cache.type = tmp;
175             }
176             uint64_t value = static_cast<uint64_t>(strtoull(totalbuffer.CurWord(), &end, DEC_BASE));
177             CHECK_TRUE(value >= 0, false, "%s:NetworkPlugin, strtoull value failed", __func__);
178             if ((index == UID_INDEX) && (uid != static_cast<int32_t>(value))) {
179                 break;
180             }
181             if (index == RX_INDEX) {
182                 uint64_t rx_bytes = value;
183                 cache.rx = rx_bytes;
184                 cell.rx += rx_bytes;
185             }
186             if (index == TX_INDEX) {
187                 uint64_t tx_bytes = value;
188                 cache.tx = tx_bytes;
189                 cell.tx += tx_bytes;
190                 AddNetDetails(cell, cache);
191             }
192         }
193     } while (totalbuffer.NextLine());
194 
195     clock_gettime(CLOCK_REALTIME, &cell.ts);
196 
197     return true;
198 }
199 
AddNetDetails(NetworkCell & cell,NetDetails & data)200 void NetworkPlugin::AddNetDetails(NetworkCell& cell, NetDetails& data)
201 {
202     bool finded = false;
203 
204     // 处理重复数据
205     for (auto it = cell.details.begin(); it != cell.details.end(); it++) {
206         if (it->type == data.type) {
207             it->tx += data.tx;
208             it->rx += data.rx;
209             finded = true;
210         }
211     }
212 
213     if (!finded) {
214         cell.details.push_back(data);
215     }
216 }
217