@@ -147,8 +147,9 @@ class ServerRouterImpl final : public ServerRouter
147147
148148 ~GatewayImpl ()
149149 {
150- router_.unregisterGateway (endpoint_, true );
151150 ::syslog (LOG_DEBUG, " ~Gateway(cl=%zu, tag=%zu)." , endpoint_.getClientId(), endpoint_.getTag());
151+
152+ router_.onGatewayDisposal (endpoint_);
152153 }
153154
154155 // detail::Gateway
@@ -159,6 +160,10 @@ class ServerRouterImpl final : public ServerRouter
159160 {
160161 return static_cast <int >(ErrorCode::NotConnected);
161162 }
163+ if (!router_.isRegisteredGateway (endpoint_))
164+ {
165+ return static_cast <int >(ErrorCode::Disconnected);
166+ }
162167
163168 Route_1_0 route{&router_.memory_ };
164169
@@ -183,16 +188,8 @@ class ServerRouterImpl final : public ServerRouter
183188
184189 void subscribe (EventHandler event_handler) override
185190 {
186- if (event_handler)
187- {
188- event_handler_ = std::move (event_handler);
189- router_.registerGateway (endpoint_, *this );
190- }
191- else
192- {
193- event_handler_ = nullptr ;
194- router_.unregisterGateway (endpoint_, false );
195- }
191+ event_handler_ = std::move (event_handler);
192+ router_.onGatewaySubscription (endpoint_);
196193 }
197194
198195 private:
@@ -211,24 +208,62 @@ class ServerRouterImpl final : public ServerRouter
211208 return connected_client_ids_.find (endpoint.getClientId ()) != connected_client_ids_.end ();
212209 }
213210
214- void registerGateway (const Endpoint& endpoint, GatewayImpl& gateway)
211+ CETL_NODISCARD bool isRegisteredGateway (const Endpoint& endpoint) const noexcept
212+ {
213+ return endpoint_to_gateway_.find (endpoint) != endpoint_to_gateway_.end ();
214+ }
215+
216+ template <typename Action>
217+ void findAndActOnRegisteredGateway (const Endpoint endpoint, Action&& action)
218+ {
219+ const auto ep_to_gw = endpoint_to_gateway_.find (endpoint);
220+ if (ep_to_gw != endpoint_to_gateway_.end ())
221+ {
222+ const auto gateway = ep_to_gw->second .lock ();
223+ if (gateway)
224+ {
225+ std::forward<Action>(action)(*gateway, ep_to_gw);
226+ }
227+ }
228+ }
229+
230+ void onGatewaySubscription (const Endpoint endpoint)
215231 {
216- endpoint_to_gateway_[endpoint] = gateway.shared_from_this ();
217232 if (isConnected (endpoint))
218233 {
219- gateway.event (detail::Gateway::Event::Connected{});
234+ findAndActOnRegisteredGateway (endpoint, [](auto & gateway, auto ) {
235+ //
236+ gateway.event (detail::Gateway::Event::Connected{});
237+ });
220238 }
221239 }
222240
223- void unregisterGateway (const Endpoint& endpoint, const bool is_disposed = false )
241+ // / Unregisters the gateway associated with the given endpoint.
242+ // /
243+ // / Called on the gateway disposal (correspondingly on its channel destruction).
244+ // / The "dying" gateway wishes to notify the remote client router about its disposal.
245+ // / This local router fulfills the wish if the gateway was registered and the client router is connected.
246+ // /
247+ void onGatewayDisposal (const Endpoint& endpoint)
224248 {
225- endpoint_to_gateway_.erase (endpoint);
249+ const bool was_registered = ( endpoint_to_gateway_.erase (endpoint) > 0 );
226250
227- // Notify " remote" router about the gateway disposal.
228- // The router will deliver "disconnected " event to the counterpart gateway (if it exists ).
251+ // Notify remote client router about the gateway disposal (aka channel completion) .
252+ // The router will propagate "ChEnd " event to the counterpart gateway (if it's registered ).
229253 //
230- if (is_disposed && isConnected (endpoint))
254+ if (was_registered && isConnected (endpoint))
231255 {
256+ Route_1_0 route{&memory_};
257+ auto & channel_end = route.set_channel_end ();
258+ channel_end.tag = endpoint.getTag ();
259+ channel_end.error_code = 0 ; // No error b/c it's a normal channel completion.
260+
261+ const int result = tryPerformOnSerialized (route, [this , &endpoint](const auto payload) {
262+ //
263+ return server_pipe_->send (endpoint.getClientId (), {{payload}});
264+ });
265+ // Best efforts strategy - gateway anyway is gone, so nowhere to report.
266+ (void ) result;
232267 }
233268 }
234269
@@ -318,7 +353,8 @@ class ServerRouterImpl final : public ServerRouter
318353 const auto si_to_cf = service_id_to_channel_factory_.find (route_ch_msg.service_id );
319354 if (si_to_cf != service_id_to_channel_factory_.end ())
320355 {
321- auto gateway = GatewayImpl::create (*this , endpoint);
356+ auto gateway = GatewayImpl::create (*this , endpoint);
357+ endpoint_to_gateway_[endpoint] = gateway;
322358 si_to_cf->second (gateway, msg_payload);
323359 }
324360 }
0 commit comments