blob: 3395cef9632bcde46285669a222ae7eff1504ad8 [file] [log] [blame]
Adedeji Adebisi684ec912021-07-22 18:07:52 +00001// Copyright 2021 Google LLC
2//
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 "analyzer.hpp"
16#include "histogram.hpp"
Adedeji Adebisi684ec912021-07-22 18:07:52 +000017#include "main.hpp"
nitroglycerine49dcde12023-03-14 07:24:39 -070018#include "sensorhelper.hpp"
Adedeji Adebisi684ec912021-07-22 18:07:52 +000019
20#include <ncurses.h>
21#include <stdlib.h>
22#include <systemd/sd-bus.h>
23
24#include <unordered_map>
25
26bool IS_USER_BUS = false; // User bus or System bus?
27extern sd_bus* g_bus;
28extern DBusConnectionSnapshot* g_connection_snapshot;
29static std::unordered_map<uint64_t, uint64_t> in_flight_methodcalls;
30
Sui Chen8c5208f2023-04-21 14:10:05 -070031extern bool g_sensor_update_thread_active;
32extern std::string g_snapshot_update_bus_cxn;
33extern int g_snapshot_update_bus_cxn_id;
34extern int GetConnectionNumericID(const std::string& unique_name);
35
Adedeji Adebisi684ec912021-07-22 18:07:52 +000036namespace dbus_top_analyzer
37{
nitroglycerine49dcde12023-03-14 07:24:39 -070038extern DBusTopStatistics g_dbus_statistics;
39extern Histogram<float> g_mc_time_histogram;
Adedeji Adebisi684ec912021-07-22 18:07:52 +000040} // namespace dbus_top_analyzer
41
Patrick Williamsf5c0b9d2023-03-14 09:31:01 -050042static void TrackMessage([[maybe_unused]] sd_bus_message* m) {}
Adedeji Adebisi684ec912021-07-22 18:07:52 +000043// Obtain a Monitoring DBus connection
44int AcquireBus(sd_bus** ret)
45{
46 int r;
47 r = sd_bus_new(ret);
48 if (r < 0)
49 {
50 printf("Could not allocate bus: %s\n", strerror(-r));
51 return 0;
52 }
53 r = sd_bus_set_monitor(*ret, true);
54 if (r < 0)
55 {
56 printf("Could not set monitor mode: %s\n", strerror(-r));
57 return 0;
58 }
59 r = sd_bus_negotiate_creds(*ret, true, _SD_BUS_CREDS_ALL);
60 if (r < 0)
61 {
62 printf("Could not enable credentials: %s\n", strerror(-r));
63 return 0;
64 }
65 r = sd_bus_negotiate_timestamp(*ret, true);
66 if (r < 0)
67 {
68 printf("Could not enable timestamps: %s\n", strerror(-r));
69 return 0;
70 }
71 r = sd_bus_negotiate_fds(*ret, true);
72 if (r < 0)
73 {
74 printf("Could not enable fds: %s\n", strerror(-r));
75 return 0;
76 }
77 r = sd_bus_set_bus_client(*ret, true);
78 if (r < 0)
79 {
80 printf("Could not enable bus client: %s\n", strerror(-r));
81 return 0;
82 }
83 if (IS_USER_BUS)
84 {
85 r = sd_bus_set_address(*ret, "haha");
86 if (r < 0)
87 {
88 printf("Could not set user bus: %s\n", strerror(-r));
89 return 0;
90 }
91 }
92 else
93 {
94 r = sd_bus_set_address(*ret, "unix:path=/run/dbus/system_bus_socket");
95 if (r < 0)
96 {
97 printf("Could not set system bus: %s\n", strerror(-r));
98 return 0;
99 }
100 }
101 r = sd_bus_start(*ret);
102 if (r < 0)
103 {
104 printf("Could not connect to bus: %s\n", strerror(-r));
105 return 0;
106 }
107 return r;
108}
109
110void DbusCaptureThread()
111{
112 int r;
113 // Become Monitor
114 uint32_t flags = 0;
115 sd_bus_message* message;
116 sd_bus_error error = SD_BUS_ERROR_NULL;
117 r = sd_bus_message_new_method_call(
118 g_bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus",
119 "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
120 if (r < 0)
121 {
122 printf("Could not create the BecomeMonitor function call\n");
123 exit(0);
124 }
125 // Match conditions
126 r = sd_bus_message_open_container(message, 'a', "s");
127 if (r < 0)
128 {
129 printf("Could not open container\n");
130 exit(0);
131 }
132 r = sd_bus_message_close_container(message);
133 if (r < 0)
134 {
135 printf("Could not close container\n");
136 exit(0);
137 }
138 r = sd_bus_message_append_basic(message, 'u', &flags);
139 if (r < 0)
140 {
141 printf("Could not append flags\n");
142 exit(0);
143 }
144 r = sd_bus_call(g_bus, message, 0, &error, nullptr);
145 if (r < 0)
146 {
147 printf("Could not call org.freedesktop.DBus.Monitoring.BecomeMonitor "
148 "%d, %s\n",
149 r, strerror(-r));
150 exit(0);
151 }
152 const char* unique_name;
153 r = sd_bus_get_unique_name(g_bus, &unique_name);
154 if (r < 0)
155 {
156 printf("Could not get unique name: %s\n", strerror(-r));
157 exit(0);
158 }
159 // Enter packet processing loop
160 while (true)
161 {
162 struct sd_bus_message* m = nullptr;
163 r = sd_bus_process(g_bus, &m);
164 if (m != nullptr)
165 {
166 if (r < 0)
167 {
168 printf("Failed to call sd_bus_process: %s\n", strerror(-r));
169 }
170 uint8_t type;
171 r = sd_bus_message_get_type(m, &type);
172 const char* path = sd_bus_message_get_path(m);
173 // const char* iface = sd_bus_message_get_interface(m);
174 const char* sender = sd_bus_message_get_sender(m);
175 const char* destination = sd_bus_message_get_destination(m);
176 const char* interface = sd_bus_message_get_interface(m);
177 const char* member = sd_bus_message_get_member(m);
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000178
Sui Chen8c5208f2023-04-21 14:10:05 -0700179 // For looking up the unique connection name for sender and
180 // destination
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000181 std::string sender_uniq, dest_uniq;
Sui Chen8c5208f2023-04-21 14:10:05 -0700182 bool should_ignore = false;
183
184 if (g_sensor_update_thread_active &&
185 g_snapshot_update_bus_cxn != "")
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000186 {
Sui Chen8c5208f2023-04-21 14:10:05 -0700187 int cxn_id = -999;
188 if (sender != nullptr)
189 {
190 cxn_id = GetConnectionNumericID(std::string(sender));
191 }
192 if (destination != nullptr)
193 {
194 cxn_id = GetConnectionNumericID(std::string(destination));
195 }
196
197 // Reason for this: The connection may be the connection from
198 // the update thread plus 1, example: :1.10000 vs :1.10001 Not
199 // sure where the new connection comes from. FIXME
200 if (cxn_id <= 4 + g_snapshot_update_bus_cxn_id &&
201 cxn_id >= g_snapshot_update_bus_cxn_id)
202 {
203 should_ignore = true;
204 }
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000205 }
Sui Chen8c5208f2023-04-21 14:10:05 -0700206
207 if (!should_ignore)
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000208 {
Sui Chen8c5208f2023-04-21 14:10:05 -0700209 // TODO: This is for the bottom-left window
210 TrackMessage(m);
211
212 if (sender != nullptr)
213 {
214 sender_uniq =
215 g_connection_snapshot->GetUniqueNameIfExists(sender);
216 }
217 if (destination != nullptr)
218 {
219 dest_uniq = g_connection_snapshot->GetUniqueNameIfExists(
220 destination);
221 }
222 // This is for the bottom-right window
223 dbus_top_analyzer::g_dbus_statistics.OnNewDBusMessage(
224 sender_uniq.c_str(), dest_uniq.c_str(), interface, path,
225 member, type, m);
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000226 }
Sui Chen8c5208f2023-04-21 14:10:05 -0700227
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000228 sd_bus_message_unref(m);
229 }
230 r = sd_bus_wait(g_bus,
231 (uint64_t)(GetSummaryIntervalInMillises() * 1000));
232 if (r < 0)
233 {
234 printf("Failed to wait on bus: %s\n", strerror(-r));
235 abort();
236 }
237 // Perform one analysis step
238 dbus_top_analyzer::Process();
239 }
Patrick Williamsc3aa2a82023-05-10 07:51:38 -0500240}