blob: 38acfc4390ce8c99532a0c5c04c2e6621a0ea433 [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
31namespace dbus_top_analyzer
32{
nitroglycerine49dcde12023-03-14 07:24:39 -070033extern DBusTopStatistics g_dbus_statistics;
34extern Histogram<float> g_mc_time_histogram;
Adedeji Adebisi684ec912021-07-22 18:07:52 +000035} // namespace dbus_top_analyzer
36
Patrick Williamsf5c0b9d2023-03-14 09:31:01 -050037static void TrackMessage([[maybe_unused]] sd_bus_message* m) {}
Adedeji Adebisi684ec912021-07-22 18:07:52 +000038// Obtain a Monitoring DBus connection
39int AcquireBus(sd_bus** ret)
40{
41 int r;
42 r = sd_bus_new(ret);
43 if (r < 0)
44 {
45 printf("Could not allocate bus: %s\n", strerror(-r));
46 return 0;
47 }
48 r = sd_bus_set_monitor(*ret, true);
49 if (r < 0)
50 {
51 printf("Could not set monitor mode: %s\n", strerror(-r));
52 return 0;
53 }
54 r = sd_bus_negotiate_creds(*ret, true, _SD_BUS_CREDS_ALL);
55 if (r < 0)
56 {
57 printf("Could not enable credentials: %s\n", strerror(-r));
58 return 0;
59 }
60 r = sd_bus_negotiate_timestamp(*ret, true);
61 if (r < 0)
62 {
63 printf("Could not enable timestamps: %s\n", strerror(-r));
64 return 0;
65 }
66 r = sd_bus_negotiate_fds(*ret, true);
67 if (r < 0)
68 {
69 printf("Could not enable fds: %s\n", strerror(-r));
70 return 0;
71 }
72 r = sd_bus_set_bus_client(*ret, true);
73 if (r < 0)
74 {
75 printf("Could not enable bus client: %s\n", strerror(-r));
76 return 0;
77 }
78 if (IS_USER_BUS)
79 {
80 r = sd_bus_set_address(*ret, "haha");
81 if (r < 0)
82 {
83 printf("Could not set user bus: %s\n", strerror(-r));
84 return 0;
85 }
86 }
87 else
88 {
89 r = sd_bus_set_address(*ret, "unix:path=/run/dbus/system_bus_socket");
90 if (r < 0)
91 {
92 printf("Could not set system bus: %s\n", strerror(-r));
93 return 0;
94 }
95 }
96 r = sd_bus_start(*ret);
97 if (r < 0)
98 {
99 printf("Could not connect to bus: %s\n", strerror(-r));
100 return 0;
101 }
102 return r;
103}
104
105void DbusCaptureThread()
106{
107 int r;
108 // Become Monitor
109 uint32_t flags = 0;
110 sd_bus_message* message;
111 sd_bus_error error = SD_BUS_ERROR_NULL;
112 r = sd_bus_message_new_method_call(
113 g_bus, &message, "org.freedesktop.DBus", "/org/freedesktop/DBus",
114 "org.freedesktop.DBus.Monitoring", "BecomeMonitor");
115 if (r < 0)
116 {
117 printf("Could not create the BecomeMonitor function call\n");
118 exit(0);
119 }
120 // Match conditions
121 r = sd_bus_message_open_container(message, 'a', "s");
122 if (r < 0)
123 {
124 printf("Could not open container\n");
125 exit(0);
126 }
127 r = sd_bus_message_close_container(message);
128 if (r < 0)
129 {
130 printf("Could not close container\n");
131 exit(0);
132 }
133 r = sd_bus_message_append_basic(message, 'u', &flags);
134 if (r < 0)
135 {
136 printf("Could not append flags\n");
137 exit(0);
138 }
139 r = sd_bus_call(g_bus, message, 0, &error, nullptr);
140 if (r < 0)
141 {
142 printf("Could not call org.freedesktop.DBus.Monitoring.BecomeMonitor "
143 "%d, %s\n",
144 r, strerror(-r));
145 exit(0);
146 }
147 const char* unique_name;
148 r = sd_bus_get_unique_name(g_bus, &unique_name);
149 if (r < 0)
150 {
151 printf("Could not get unique name: %s\n", strerror(-r));
152 exit(0);
153 }
154 // Enter packet processing loop
155 while (true)
156 {
157 struct sd_bus_message* m = nullptr;
158 r = sd_bus_process(g_bus, &m);
159 if (m != nullptr)
160 {
161 if (r < 0)
162 {
163 printf("Failed to call sd_bus_process: %s\n", strerror(-r));
164 }
165 uint8_t type;
166 r = sd_bus_message_get_type(m, &type);
167 const char* path = sd_bus_message_get_path(m);
168 // const char* iface = sd_bus_message_get_interface(m);
169 const char* sender = sd_bus_message_get_sender(m);
170 const char* destination = sd_bus_message_get_destination(m);
171 const char* interface = sd_bus_message_get_interface(m);
172 const char* member = sd_bus_message_get_member(m);
173 // TODO: This is for the bottom-left window
174 TrackMessage(m);
175
176 // Look up the unique connection name for sender and destination
177 std::string sender_uniq, dest_uniq;
178 if (sender != nullptr)
179 {
180 sender_uniq =
181 g_connection_snapshot->GetUniqueNameIfExists(sender);
182 }
183 if (destination != nullptr)
184 {
185 dest_uniq =
186 g_connection_snapshot->GetUniqueNameIfExists(destination);
187 }
188 // This is for the bottom-right window
189 dbus_top_analyzer::g_dbus_statistics.OnNewDBusMessage(
nitroglycerine49dcde12023-03-14 07:24:39 -0700190 sender_uniq.c_str(), dest_uniq.c_str(), interface, path, member,
Adedeji Adebisi684ec912021-07-22 18:07:52 +0000191 type, m);
192 sd_bus_message_unref(m);
193 }
194 r = sd_bus_wait(g_bus,
195 (uint64_t)(GetSummaryIntervalInMillises() * 1000));
196 if (r < 0)
197 {
198 printf("Failed to wait on bus: %s\n", strerror(-r));
199 abort();
200 }
201 // Perform one analysis step
202 dbus_top_analyzer::Process();
203 }
204}