Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include "IpcModule.h"
21 : #include "RialtoClientLogging.h"
22 :
23 : namespace firebolt::rialto::client
24 : {
25 413 : IpcModule::IpcModule(IIpcClient &ipcClient) : m_ipc{ipcClient}
26 : {
27 413 : RIALTO_CLIENT_LOG_DEBUG("entry:");
28 : }
29 :
30 413 : IpcModule::~IpcModule()
31 : {
32 413 : RIALTO_CLIENT_LOG_DEBUG("entry:");
33 : }
34 :
35 624 : bool IpcModule::unsubscribeFromAllEvents(const std::shared_ptr<ipc::IChannel> &ipcChannel)
36 : {
37 624 : if (!ipcChannel)
38 : {
39 80 : return false;
40 : }
41 :
42 544 : bool result = true;
43 3726 : for (auto it = m_eventTags.begin(); it != m_eventTags.end(); it++)
44 : {
45 3182 : if (!ipcChannel->unsubscribe(*it))
46 : {
47 3 : result = false;
48 : }
49 : }
50 544 : m_eventTags.clear();
51 :
52 544 : return result;
53 : }
54 :
55 636 : bool IpcModule::attachChannel()
56 : {
57 : // get the channel
58 636 : std::shared_ptr<ipc::IChannel> ipcChannel{getConnectedChannel()};
59 :
60 : // If not connected, try to recover and reconnect first
61 636 : if (!ipcChannel)
62 : {
63 93 : RIALTO_CLIENT_LOG_WARN("Channel not connected. Trying to recover...");
64 93 : if (!m_ipc.reconnect())
65 : {
66 91 : RIALTO_CLIENT_LOG_ERROR("Reconnection failed.");
67 91 : return false;
68 : }
69 :
70 2 : ipcChannel = getConnectedChannel();
71 2 : if (!ipcChannel)
72 : {
73 1 : RIALTO_CLIENT_LOG_ERROR("Failed to get the ipc channel");
74 1 : return false;
75 : }
76 : }
77 :
78 : // create the RPC stubs
79 544 : if (!createRpcStubs(ipcChannel))
80 : {
81 0 : RIALTO_CLIENT_LOG_ERROR("Could not create the ipc module stubs");
82 0 : return false;
83 : }
84 :
85 : // install listeners
86 544 : if (!subscribeToEvents(ipcChannel))
87 : {
88 4 : RIALTO_CLIENT_LOG_ERROR("Could not subscribe to ipc module events");
89 4 : unsubscribeFromAllEvents(ipcChannel);
90 4 : return false;
91 : }
92 :
93 540 : m_ipcChannel = ipcChannel;
94 :
95 540 : return true;
96 636 : }
97 :
98 620 : void IpcModule::detachChannel()
99 : {
100 : // uninstalls listeners
101 620 : if (!unsubscribeFromAllEvents(m_ipcChannel.lock()))
102 : {
103 80 : RIALTO_CLIENT_LOG_ERROR("Failed to unsubscribe to some ipc module events, this can lead to core dumps in IPC");
104 : }
105 :
106 : // remove IPC
107 620 : m_ipcChannel.reset();
108 : }
109 :
110 1038 : bool IpcModule::reattachChannelIfRequired()
111 : {
112 1038 : std::shared_ptr<ipc::IChannel> ipcChannel = m_ipcChannel.lock();
113 1038 : if ((nullptr == ipcChannel) || (!ipcChannel->isConnected()))
114 : {
115 223 : RIALTO_CLIENT_LOG_INFO("Ipc channel no longer connected, attach new channel");
116 223 : detachChannel();
117 223 : if (!attachChannel())
118 : {
119 80 : RIALTO_CLIENT_LOG_ERROR("Failed attach to the ipc channel");
120 80 : return false;
121 : }
122 : }
123 :
124 958 : return true;
125 1038 : }
126 :
127 638 : std::shared_ptr<ipc::IChannel> IpcModule::getConnectedChannel()
128 : {
129 : // Split for Coverity clarity due to independent lifetime
130 638 : std::weak_ptr<ipc::IChannel> weakChannel = m_ipc.getChannel();
131 638 : std::shared_ptr<ipc::IChannel> ipcChannel = weakChannel.lock();
132 638 : if (ipcChannel && ipcChannel->isConnected())
133 : {
134 544 : return ipcChannel;
135 : }
136 94 : return nullptr;
137 638 : }
138 : }; // namespace firebolt::rialto::client
|