blob: 6dd649365319307ccc54470a3abea11e8be3c7d0 [file] [log] [blame]
Andrew Geissler3b025e62019-02-01 10:33:54 -06001#include "processing.hpp"
2
3#include <boost/algorithm/string/predicate.hpp>
Andrew Geissler70461892019-02-27 09:57:37 -06004#include <iostream>
Andrew Geissler3b025e62019-02-01 10:33:54 -06005
6bool getWellKnown(
7 const boost::container::flat_map<std::string, std::string>& owners,
8 const std::string& request, std::string& wellKnown)
9{
10 // If it's already a well known name, just return
11 if (!boost::starts_with(request, ":"))
12 {
13 wellKnown = request;
14 return true;
15 }
16
17 auto it = owners.find(request);
18 if (it == owners.end())
19 {
20 return false;
21 }
22 wellKnown = it->second;
23 return true;
24}
Andrew Geissler82815da2019-02-04 12:19:41 -060025
26bool needToIntrospect(const std::string& processName,
27 const WhiteBlackList& whiteList,
28 const WhiteBlackList& blackList)
29{
30 auto inWhitelist =
31 std::find_if(whiteList.begin(), whiteList.end(),
32 [&processName](const auto& prefix) {
33 return boost::starts_with(processName, prefix);
34 }) != whiteList.end();
35
36 // This holds full service names, not prefixes
37 auto inBlacklist = blackList.find(processName) != blackList.end();
38
39 return inWhitelist && !inBlacklist;
40}
Andrew Geissler20679262019-02-11 20:20:40 -060041
42void processNameChangeDelete(
43 boost::container::flat_map<std::string, std::string>& nameOwners,
44 const std::string& wellKnown, const std::string& oldOwner,
45 interface_map_type& interfaceMap, AssociationOwnersType& assocOwners,
46 AssociationInterfaces& assocInterfaces,
47 sdbusplus::asio::object_server& server)
48{
49 if (boost::starts_with(oldOwner, ":"))
50 {
51 auto it = nameOwners.find(oldOwner);
52 if (it != nameOwners.end())
53 {
54 nameOwners.erase(it);
55 }
56 }
57 // Connection removed
58 interface_map_type::iterator pathIt = interfaceMap.begin();
59 while (pathIt != interfaceMap.end())
60 {
61 // If an associations interface is being removed,
62 // also need to remove the corresponding associations
63 // objects and properties.
64 auto ifaces = pathIt->second.find(wellKnown);
65 if (ifaces != pathIt->second.end())
66 {
67 auto assoc = std::find(ifaces->second.begin(), ifaces->second.end(),
68 ASSOCIATIONS_INTERFACE);
69 if (assoc != ifaces->second.end())
70 {
71 removeAssociation(pathIt->first, wellKnown, server, assocOwners,
72 assocInterfaces);
73 }
74 }
75 pathIt->second.erase(wellKnown);
76 if (pathIt->second.empty())
77 {
78 // If the last connection to the object is gone,
79 // delete the top level object
80 pathIt = interfaceMap.erase(pathIt);
81 continue;
82 }
83 pathIt++;
84 }
85}
Andrew Geissler70461892019-02-27 09:57:37 -060086
87void processInterfaceAdded(interface_map_type& interfaceMap,
88 const sdbusplus::message::object_path& objPath,
89 const InterfacesAdded& intfAdded,
90 const std::string& wellKnown,
91 AssociationOwnersType& assocOwners,
92 AssociationInterfaces& assocInterfaces,
93 sdbusplus::asio::object_server& server)
94{
95 auto& ifaceList = interfaceMap[objPath.str];
96
97 for (const auto& interfacePair : intfAdded)
98 {
99 ifaceList[wellKnown].emplace(interfacePair.first);
100
101 if (interfacePair.first == ASSOCIATIONS_INTERFACE)
102 {
103 const sdbusplus::message::variant<std::vector<Association>>*
104 variantAssociations = nullptr;
105 for (const auto& interface : interfacePair.second)
106 {
107 if (interface.first == "associations")
108 {
109 variantAssociations = &(interface.second);
110 }
111 }
112 if (variantAssociations == nullptr)
113 {
114 std::cerr << "Illegal association found on " << wellKnown
115 << "\n";
116 continue;
117 }
118 std::vector<Association> associations =
119 sdbusplus::message::variant_ns::get<std::vector<Association>>(
120 *variantAssociations);
121 associationChanged(server, associations, objPath.str, wellKnown,
122 assocOwners, assocInterfaces);
123 }
124 }
125
126 // To handle the case where an object path is being created
127 // with 2 or more new path segments, check if the parent paths
128 // of this path are already in the interface map, and add them
129 // if they aren't with just the default freedesktop interfaces.
130 // This would be done via introspection if they would have
131 // already existed at startup. While we could also introspect
132 // them now to do the work, we know there aren't any other
133 // interfaces or we would have gotten signals for them as well,
134 // so take a shortcut to speed things up.
135 //
136 // This is all needed so that mapper operations can be done
137 // on the new parent paths.
138 using iface_map_iterator = interface_map_type::iterator;
139 using iface_map_value_type =
140 boost::container::flat_map<std::string,
141 boost::container::flat_set<std::string>>;
142 using name_map_iterator = iface_map_value_type::iterator;
143
144 static const boost::container::flat_set<std::string> defaultIfaces{
145 "org.freedesktop.DBus.Introspectable", "org.freedesktop.DBus.Peer",
146 "org.freedesktop.DBus.Properties"};
147
148 std::string parent = objPath.str;
149 auto pos = parent.find_last_of('/');
150
151 while (pos != std::string::npos)
152 {
153 parent = parent.substr(0, pos);
154
155 std::pair<iface_map_iterator, bool> parentEntry =
156 interfaceMap.insert(std::make_pair(parent, iface_map_value_type{}));
157
158 std::pair<name_map_iterator, bool> ifaceEntry =
159 parentEntry.first->second.insert(
160 std::make_pair(wellKnown, defaultIfaces));
161
162 if (!ifaceEntry.second)
163 {
164 // Entry was already there for this name so done.
165 break;
166 }
167
168 pos = parent.find_last_of('/');
169 }
170}