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