Set nullptr to the listener ptr
[platform/core/appfw/rpc-port.git] / src / proxy-internal.cc
1 /*
2  * Copyright (c) 2017 - 2021 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <aul_svc.h>
18 #include <dlog.h>
19 #include <sys/socket.h>
20 #include <sys/types.h>
21 #include <uuid.h>
22
23 #include <memory>
24 #include <utility>
25 #include <vector>
26
27 #include "aul-internal.hh"
28 #include "debug-port-internal.hh"
29 #include "exception-internal.hh"
30 #include "include/rpc-port-internal.h"
31 #include "log-private.hh"
32 #include "proxy-internal.hh"
33 #include "request-internal.hh"
34 #include "response-internal.hh"
35
36 #define EILLEGALACCESS 127
37
38 namespace rpc_port {
39 namespace internal {
40 namespace {
41
42 constexpr const char kPortTypeMain[] = "main";
43 constexpr const char kPortTypeDelegate[] = "delegate";
44
45 std::string GenInstance() {
46   uuid_t u;
47   uuid_generate(u);
48   char uuid[37];
49   uuid_unparse(u, uuid);
50   return std::string(uuid) + "@" + Aul::GetAppId(getpid());
51 }
52
53 int SendRequest(ClientSocket* client, const Request& request) {
54   tizen_base::Parcel parcel;
55   parcel.WriteParcelable(const_cast<Request&>(request));
56   const std::vector<uint8_t>& raw = parcel.GetRaw();
57   size_t size = raw.size();
58   int ret = client->Send(reinterpret_cast<void*>(&size), sizeof(size));
59   if (ret != 0) {
60     _E("Send() is failed. error(%d)", ret);
61     return -1;
62   }
63
64   ret = client->Send(raw.data(), raw.size());
65   if (ret != 0) {
66     _E("Send() is failed. error(%d)", ret);
67     return -1;
68   }
69
70   return 0;
71 }
72
73 int ReceiveResponse(ClientSocket* client, Response** response) {
74   size_t size = 0;
75   int ret = client->Receive(reinterpret_cast<void*>(&size), sizeof(size));
76   if (ret != 0) {
77     _E("Receive() is failed. error(%d)", ret);
78     return -1;
79   }
80
81   std::vector<uint8_t> buf(size);
82   ret = client->Receive(buf.data(), size);
83   if (ret != 0) {
84     _E("Receive() is failed. error(%d)", ret);
85     return -1;
86   }
87
88   tizen_base::Parcel parcel(buf.data(), buf.size());
89   *response = new (std::nothrow) Response();
90   if (*response == nullptr) {
91     _E("Out of memory");
92     return -1;
93   }
94
95   parcel.ReadParcelable(*response);
96   return 0;
97 }
98
99 }  // namespace
100
101 Proxy::Proxy() {
102   _D("Proxy::Proxy()");
103 }
104
105 Proxy::~Proxy() {
106   std::lock_guard<std::recursive_mutex> lock(GetMutex());
107   _D("Proxy::~Proxy()");
108   listener_ = nullptr;
109   UnsetIdler();
110   UnsetConnTimer();
111   Cancel();
112 }
113
114 int Proxy::Connect(bool sync) {
115   std::lock_guard<std::recursive_mutex> lock(GetMutex());
116   fds_[0] = 0;
117   fds_[1] = 0;
118
119   std::string port_path = Aul::GetPortPath(real_appid_, port_name_,
120       rpc_port_get_target_uid());
121   std::string instance = GenInstance();
122
123   // Main Port
124   main_client_.reset(Client::Create(this, port_path));
125   if (main_client_.get() == nullptr)
126     return RPC_PORT_ERROR_IO_ERROR;
127
128   Request request(instance.c_str(), kPortTypeMain);
129   int ret = SendRequest(main_client_.get(), request);
130   if (ret != 0)
131     return RPC_PORT_ERROR_IO_ERROR;
132
133   if (sync) {
134     Response* response = nullptr;
135     ret = ReceiveResponse(main_client_.get(), &response);
136     if (ret != 0)
137       return RPC_PORT_ERROR_IO_ERROR;
138
139     std::unique_ptr<Response> response_auto(response);
140     if (response->GetResult() != 0) {
141       _E("Permission denied");
142       return RPC_PORT_ERROR_PERMISSION_DENIED;
143     }
144
145     main_client_->SetNonblock();
146     fds_[0] = main_client_->RemoveFd();
147   } else {
148     ret = main_client_->Watch();
149     if (ret != 0)
150       return RPC_PORT_ERROR_IO_ERROR;
151   }
152
153   // Delegate Port
154   delegate_client_.reset(Client::Create(this, port_path));
155   if (delegate_client_.get() == nullptr)
156     return RPC_PORT_ERROR_IO_ERROR;
157
158   request.SetPortType(kPortTypeDelegate);
159   ret = SendRequest(delegate_client_.get(), request);
160   if (ret != 0)
161     return RPC_PORT_ERROR_IO_ERROR;
162
163   if (sync) {
164     Response* response = nullptr;
165     ret = ReceiveResponse(delegate_client_.get(), &response);
166     if (ret != 0)
167       return RPC_PORT_ERROR_IO_ERROR;
168
169     std::unique_ptr<Response> response_auto(response);
170     if (response->GetResult() != 0) {
171       _E("Permission denied");
172       return RPC_PORT_ERROR_PERMISSION_DENIED;
173     }
174
175     delegate_client_->SetNonblock();
176     fds_[1] = delegate_client_->RemoveFd();
177   } else {
178     ret = delegate_client_->Watch();
179     if (ret != 0)
180       return RPC_PORT_ERROR_IO_ERROR;
181   }
182
183   return RPC_PORT_ERROR_NONE;
184 }
185
186 int Proxy::Connect(std::string appid, std::string port_name,
187     IEventListener* listener) {
188   if (listener == nullptr)
189     return RPC_PORT_ERROR_INVALID_PARAMETER;
190
191   std::lock_guard<std::recursive_mutex> lock(GetMutex());
192   if (listener_ != nullptr) {
193     _D("Already requested");
194     return RPC_PORT_ERROR_INVALID_PARAMETER;
195   }
196
197   listener_ = listener;
198   target_appid_ = std::move(appid);
199   port_name_ = std::move(port_name);
200   SetRealAppId(target_appid_);
201
202   UnsetConnTimer();
203   int ret = Aul::PrepareStub(real_appid_, port_name_,
204       rpc_port_get_target_uid());
205   if (ret != RPC_PORT_ERROR_NONE) {
206     listener_ = nullptr;
207     return ret;
208   }
209
210   ret = Watch();
211   if (ret != 0) {
212     listener_ = nullptr;
213     return RPC_PORT_ERROR_IO_ERROR;
214   }
215
216   return RPC_PORT_ERROR_NONE;
217 }
218
219 int Proxy::ConnectSync(std::string appid, std::string port_name,
220     IEventListener* listener) {
221   if (listener == nullptr)
222     return RPC_PORT_ERROR_INVALID_PARAMETER;
223
224   if (listener_ != nullptr) {
225     _W("Already requested");
226     return RPC_PORT_ERROR_INVALID_PARAMETER;
227   }
228
229   std::lock_guard<std::recursive_mutex> lock(GetMutex());
230   listener_ = listener;
231   target_appid_ = std::move(appid);
232   port_name_ = std::move(port_name);
233   SetRealAppId(target_appid_);
234
235   int ret = Aul::PrepareStub(real_appid_, port_name_,
236       rpc_port_get_target_uid());
237   if (ret != RPC_PORT_ERROR_NONE) {
238     listener_ = nullptr;
239     return ret;
240   }
241
242   bool exist = false;
243   int retry_count = 20;
244   do {
245     exist = Aul::ExistPort(real_appid_, port_name_, rpc_port_get_target_uid());
246     if (exist)
247       break;
248
249     usleep(500 * 1000);
250     retry_count--;
251   } while (retry_count > 0);
252
253   if (!exist) {
254     _E("%s:%s is not ready", real_appid_.c_str(), port_name_.c_str());
255     listener_ = nullptr;
256     return RPC_PORT_ERROR_IO_ERROR;
257   }
258
259   ret = Connect(true);
260   if (ret != RPC_PORT_ERROR_NONE) {
261     listener_ = nullptr;
262     return ret;
263   }
264
265   main_port_.reset(new ProxyPort(this, fds_[0], target_appid_, false));
266   delegate_port_.reset(new ProxyPort(this, fds_[1], target_appid_));
267   DebugPort::GetInst()->AddSession(port_name, target_appid_, fds_[0], fds_[1]);
268   listener_->OnConnected(target_appid_, main_port_.get());
269   return RPC_PORT_ERROR_NONE;
270 }
271
272 void Proxy::DisconnectPort() {
273   std::lock_guard<std::recursive_mutex> lock(GetMutex());
274   if (main_port_.get() != nullptr) {
275     DebugPort::GetInst()->RemoveSession(main_port_->GetFd());
276     main_port_.reset();
277   }
278 }
279
280 int Proxy::Watch() {
281   std::lock_guard<std::recursive_mutex> lock(GetMutex());
282   int ret = aul_rpc_port_usr_add_watch(real_appid_.c_str(), port_name_.c_str(),
283       OnPortAppeared, OnPortVanished, this, rpc_port_get_target_uid(),
284       &watch_handle_);
285   if (ret != AUL_R_OK) {
286     _E("aul_rpc_port_usr_add_watch() is failed. error(%d)", ret);
287     return -1;
288   }
289
290   SetConnTimer();
291   SetIdler();
292   return 0;
293 }
294
295 void Proxy::Cancel() {
296   std::lock_guard<std::recursive_mutex> lock(GetMutex());
297   if (watch_handle_) {
298     aul_rpc_port_remove_watch(watch_handle_);
299     watch_handle_ = nullptr;
300   }
301 }
302
303 void Proxy::SetRealAppId(const std::string& alias_appid) {
304   std::lock_guard<std::recursive_mutex> lock(GetMutex());
305   if (!real_appid_.empty())
306     return;
307
308   char* appid = nullptr;
309   int ret = aul_svc_get_appid_by_alias_appid(alias_appid.c_str(), &appid);
310   if (ret != AUL_SVC_RET_OK) {
311     real_appid_ = alias_appid;
312     return;
313   }
314
315   std::unique_ptr<char, decltype(std::free)*> appid_ptr(appid, std::free);
316   real_appid_ = std::string(appid);
317   _W("alias_appid(%s), real_appid(%s)", alias_appid.c_str(), appid);
318 }
319
320 std::recursive_mutex& Proxy::GetMutex() const {
321   return mutex_;
322 }
323
324 void Proxy::SetConnTimer() {
325   if (conn_timer_data_) {
326     _W("Already exists");
327     return;
328   }
329
330   conn_timer_data_ = CreateWeakPtr();
331   if (conn_timer_data_ == nullptr) {
332     _E("Out of memory");
333     return;
334   }
335
336   g_timeout_add_seconds(10, OnTimedOut, conn_timer_data_);
337 }
338
339 void Proxy::UnsetConnTimer() {
340   if (conn_timer_data_ == nullptr)
341     return;
342
343   GSource* source = g_main_context_find_source_by_user_data(nullptr,
344       conn_timer_data_);
345   if (source && !g_source_is_destroyed(source))
346     g_source_destroy(source);
347
348   DestroyWeakPtr(conn_timer_data_);
349   conn_timer_data_ = nullptr;
350 }
351
352 void Proxy::SetIdler() {
353   if (idler_data_) {
354     _W("Already exists");
355     return;
356   }
357
358   idler_data_ = CreateWeakPtr();
359   if (idler_data_ == nullptr) {
360     _E("Out of memory");
361     return;
362   }
363
364   g_idle_add(OnIdle, idler_data_);
365 }
366
367 void Proxy::UnsetIdler() {
368   if (idler_data_ == nullptr)
369     return;
370
371   GSource* source = g_main_context_find_source_by_user_data(nullptr,
372       idler_data_);
373   if (source && !g_source_is_destroyed(source))
374     g_source_destroy(source);
375
376   DestroyWeakPtr(idler_data_);
377   idler_data_ = nullptr;
378 }
379
380 void Proxy::OnPortAppeared(const char* app_id, const char* port_name, int pid,
381     void* user_data) {
382   _W("app_id(%s), port_name(%s), pid(%d)", app_id, port_name, pid);
383   auto* proxy = static_cast<Proxy*>(user_data);
384   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
385   proxy->UnsetIdler();
386
387   if (proxy->watch_handle_ == nullptr) {
388     _E("Invalid context");
389     return;
390   }
391
392   auto* listener = proxy->listener_;
393   if (listener == nullptr) {
394     _E("Invalid context");
395     return;
396   }
397
398   proxy->UnsetConnTimer();
399   proxy->Cancel();
400
401   int ret = proxy->Connect(false);
402   if (ret != RPC_PORT_ERROR_NONE) {
403     proxy->listener_ = nullptr;
404     if (ret == RPC_PORT_ERROR_PERMISSION_DENIED)
405       listener->OnRejected(proxy->target_appid_, ret);
406     else
407       listener->OnDisconnected(proxy->target_appid_);
408   }
409 }
410
411 void Proxy::OnPortVanished(const char* app_id, const char* port_name, int pid,
412     void* user_data) {
413   _W("app_id(%s), port_name(%s), pid(%d)", app_id, port_name, pid);
414   auto* proxy = static_cast<Proxy*>(user_data);
415   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
416   proxy->UnsetIdler();
417 }
418
419 gboolean Proxy::OnTimedOut(gpointer user_data) {
420   _E("Timed out");
421   auto* ptr = static_cast<std::weak_ptr<Proxy>*>(user_data);
422   auto proxy = ptr->lock();
423   if (proxy == nullptr) {
424     _E("Proxy is nullptr");
425     return G_SOURCE_REMOVE;
426   }
427
428   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
429   if (proxy->conn_timer_data_ == nullptr) {
430     _E("Invalid context. proxy(%p)", proxy.get());
431     return G_SOURCE_REMOVE;
432   }
433
434   proxy->Cancel();
435   DestroyWeakPtr(proxy->conn_timer_data_);
436   proxy->conn_timer_data_ = nullptr;
437
438   auto* listener = proxy->listener_;
439   if (listener == nullptr) {
440     _E("Invalid context");
441     return G_SOURCE_REMOVE;
442   }
443
444   proxy->listener_ = nullptr;
445   listener->OnRejected(proxy->target_appid_, RPC_PORT_ERROR_IO_ERROR);
446   return G_SOURCE_REMOVE;
447 }
448
449 gboolean Proxy::OnIdle(gpointer user_data) {
450   auto* ptr = static_cast<std::weak_ptr<Proxy>*>(user_data);
451   auto proxy = ptr->lock();
452   if (proxy == nullptr) {
453     _E("Proxy is nullptr");
454     return G_SOURCE_REMOVE;
455   }
456
457   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
458   if (proxy->idler_data_ == nullptr) {
459     _E("Invalid context. proxy(%p)", proxy.get());
460     return G_SOURCE_REMOVE;
461   }
462
463   DestroyWeakPtr(proxy->idler_data_);
464   proxy->idler_data_ = nullptr;
465
466   bool exist = Aul::ExistPort(proxy->real_appid_, proxy->port_name_,
467       rpc_port_get_target_uid());
468   if (exist) {
469     proxy->OnPortAppeared(proxy->real_appid_.c_str(),
470         proxy->port_name_.c_str(), -1, proxy.get());
471   } else {
472     proxy->OnPortVanished(proxy->real_appid_.c_str(),
473         proxy->port_name_.c_str(), -1, proxy.get());
474   }
475
476   return G_SOURCE_REMOVE;
477 }
478
479 Proxy::ProxyPort::ProxyPort(Proxy* parent, int fd, const std::string& id,
480     bool receive)
481     : Port(fd, id), parent_(parent) {
482   Watch(receive);
483 }
484
485 Proxy::ProxyPort::~ProxyPort() {
486   if (disconn_source_ > 0)
487     g_source_remove(disconn_source_);
488
489   if (source_ > 0)
490     g_source_remove(source_);
491
492   if (channel_ != nullptr)
493     g_io_channel_unref(channel_);
494 }
495
496 int Proxy::ProxyPort::Watch(bool receive) {
497   channel_ = g_io_channel_unix_new(GetFd());
498   if (channel_ == nullptr) {
499     _E("g_io_channel_unix_new() is failed");
500     return -1;
501   }
502
503   disconn_source_ = g_io_add_watch(channel_,
504       static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
505       Proxy::ProxyPort::OnSocketDisconnected, parent_);
506   if (disconn_source_ == 0) {
507     _E("g_io_add_watch() is failed");
508     return -1;
509   }
510
511   if (!receive)
512     return 0;
513
514   source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
515       Proxy::ProxyPort::OnDataReceived, parent_);
516   if (source_ == 0) {
517     _E("g_io_add_watch() is failed");
518     return -1;
519   }
520
521   return 0;
522 }
523
524 void Proxy::ProxyPort::SetDisconnectedSource(guint source_id) {
525   disconn_source_ = source_id;
526 }
527
528 void Proxy::ProxyPort::SetSource(guint source_id) {
529   source_ = source_id;
530 }
531
532 gboolean Proxy::ProxyPort::OnSocketDisconnected(GIOChannel* channel,
533     GIOCondition cond, gpointer user_data) {
534   auto* proxy = static_cast<Proxy*>(user_data);
535   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
536   auto* listener = proxy->listener_;
537   if (listener == nullptr) {
538     _E("Invalid context");
539     return G_SOURCE_REMOVE;
540   }
541
542   int fd = g_io_channel_unix_get_fd(channel);
543   _W("Socket was disconnected. fd(%d)", fd);
544   if (proxy->main_port_.get() != nullptr &&
545       proxy->main_port_->GetFd() == fd) {
546     proxy->main_port_->SetDisconnectedSource(0);
547   } else if (proxy->delegate_port_.get() != nullptr &&
548              proxy->delegate_port_->GetFd() == fd) {
549     proxy->delegate_port_->SetDisconnectedSource(0);
550   }
551
552   proxy->main_port_.reset();
553   proxy->delegate_port_.reset();
554   proxy->listener_ = nullptr;
555   listener->OnDisconnected(proxy->target_appid_);
556   DebugPort::GetInst()->RemoveSession(fd);
557   return G_SOURCE_REMOVE;;
558 }
559
560 gboolean Proxy::ProxyPort::OnDataReceived(GIOChannel* channel,
561     GIOCondition cond, gpointer user_data) {
562   auto* proxy = static_cast<Proxy*>(user_data);
563   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
564   auto* listener = proxy->listener_;
565   if (listener == nullptr) {
566     _E("Invalid context");
567     return G_SOURCE_REMOVE;
568   }
569
570   int fd = g_io_channel_unix_get_fd(channel);
571   if (proxy->delegate_port_->GetFd() == fd) {
572     char buffer[4];
573     if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
574       _W("Socket was disconnected by stub. fd(%d)", fd);
575       proxy->listener_ = nullptr;
576       proxy->delegate_port_->SetSource(0);
577       if (proxy->main_port_.get() != nullptr) {
578         DebugPort::GetInst()->RemoveSession(proxy->main_port_->GetFd());
579         proxy->main_port_.reset();
580       }
581       proxy->delegate_port_.reset();
582       listener->OnDisconnected(proxy->target_appid_);
583       return G_SOURCE_REMOVE;
584     }
585
586     listener->OnReceived(proxy->target_appid_);
587   }
588
589   return G_SOURCE_CONTINUE;
590 }
591
592 Proxy::Client::Client(Proxy* parent) : parent_(parent) {
593 }
594
595 Proxy::Client::~Client() {
596   if (channel_)
597     g_io_channel_unref(channel_);
598
599   if (disconn_source_ > 0)
600     g_source_remove(disconn_source_);
601
602   if (source_ > 0)
603     g_source_remove(source_);
604 }
605
606 Proxy::Client* Proxy::Client::Create(Proxy* parent,
607     const std::string& endpoint) {
608   std::unique_ptr<Proxy::Client> client;
609   try {
610     client.reset(new (std::nothrow) Proxy::Client(parent));
611   } catch (Exception& e) {
612     _E("Exception(%s) occurs", e.what());
613     return nullptr;
614   }
615
616   int ret;
617   int retry_count = 5;
618   do {
619     ret = client->Connect(endpoint);
620     if (ret == 0) {
621       break;
622     } else if (ret < 0) {
623       _D("Connect() is failed");
624       usleep(100 * 1000);
625       retry_count--;
626     }
627   } while (retry_count > 0);
628
629   if (ret != 0) {
630     _E("Connect() is failed");
631     return nullptr;
632   }
633
634   client->SetReceiveTimeout(5000);
635   _W("endpoint(%s), fd(%d)", endpoint.c_str(), client->GetFd());
636   return client.release();
637 }
638
639 int Proxy::Client::Watch() {
640   channel_ = g_io_channel_unix_new(GetFd());
641   if (channel_ == nullptr) {
642     _E("g_io_channel_unix_new() is failed");
643     return -1;
644   }
645
646   source_ = g_io_add_watch(channel_, static_cast<GIOCondition>(G_IO_IN),
647       Proxy::Client::OnResponseReceived, parent_);
648   if (source_ == 0) {
649     _E("g_io_add_watch() is failed");
650     return -1;
651   }
652
653   disconn_source_ = g_io_add_watch(channel_,
654       static_cast<GIOCondition>(G_IO_ERR | G_IO_HUP | G_IO_NVAL),
655       Proxy::Client::OnSocketDisconnected, parent_);
656   if (disconn_source_ == 0) {
657     _E("g_io_add_watch() is failed");
658     return -1;
659   }
660
661   return 0;
662 }
663
664 void Proxy::Client::SetDisconnectedSource(guint source) {
665   disconn_source_ = source;
666 }
667
668 void Proxy::Client::SetSource(guint source) {
669   source_ = source;
670 }
671
672 gboolean Proxy::Client::OnSocketDisconnected(GIOChannel* channel,
673     GIOCondition cond, gpointer user_data) {
674   auto* proxy = static_cast<Proxy*>(user_data);
675   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
676   auto* listener = proxy->listener_;
677   if (listener == nullptr) {
678     _E("Invalid context");
679     return G_SOURCE_REMOVE;
680   }
681
682   int fd = g_io_channel_unix_get_fd(channel);
683   _W("Socket was disconnected. fd(%d)", fd);
684   if (proxy->main_client_.get() != nullptr &&
685       proxy->main_client_->GetFd() == fd) {
686     proxy->main_client_->SetDisconnectedSource(0);
687   } else if (proxy->delegate_client_.get() != nullptr &&
688              proxy->delegate_client_->GetFd() == fd) {
689     proxy->delegate_client_->SetDisconnectedSource(0);
690   }
691
692   proxy->main_client_.reset();
693   proxy->delegate_client_.reset();
694   proxy->listener_ = nullptr;
695   listener->OnDisconnected(proxy->target_appid_);
696   return G_SOURCE_REMOVE;
697 }
698
699 gboolean Proxy::Client::OnResponseReceived(GIOChannel* channel,
700     GIOCondition cond, gpointer user_data) {
701   auto* proxy = static_cast<Proxy*>(user_data);
702   std::lock_guard<std::recursive_mutex> lock(proxy->GetMutex());
703   auto* listener = proxy->listener_;
704   if (listener == nullptr) {
705     _E("Invalid context");
706     return G_SOURCE_REMOVE;
707   }
708
709   bool is_delegate = false;
710   std::unique_ptr<Client> client;
711   int fd = g_io_channel_unix_get_fd(channel);
712   if (proxy->main_client_.get() != nullptr &&
713       proxy->main_client_->GetFd() == fd) {
714     client.reset(proxy->main_client_.release());
715   } else if (proxy->delegate_client_.get() != nullptr &&
716              proxy->delegate_client_->GetFd() == fd) {
717     client.reset(proxy->delegate_client_.release());
718     is_delegate = true;
719   }
720
721   if (client.get() == nullptr) {
722     _E("Unknown fd(%d)", fd);
723     return G_SOURCE_REMOVE;
724   }
725
726   client->SetSource(0);
727
728   Response* response = nullptr;
729   int ret = ReceiveResponse(client.get(), &response);
730   if (ret != 0) {
731     proxy->listener_ = nullptr;
732     proxy->main_client_.reset();
733     proxy->delegate_client_.reset();
734     listener->OnRejected(proxy->target_appid_, RPC_PORT_ERROR_IO_ERROR);
735     return G_SOURCE_REMOVE;
736   }
737
738   std::unique_ptr<Response> response_auto(response);
739   if (response->GetResult() != 0) {
740     _E("Permission denied");
741     proxy->listener_ = nullptr;
742     proxy->main_client_.reset();
743     proxy->delegate_client_.reset();
744     listener->OnRejected(proxy->target_appid_,
745         RPC_PORT_ERROR_PERMISSION_DENIED);
746     return G_SOURCE_REMOVE;
747   }
748
749   client->SetNonblock();
750   int client_fd = client->RemoveFd();
751   if (is_delegate) {
752     proxy->fds_[1] = client_fd;
753     proxy->delegate_port_.reset(
754         new ProxyPort(proxy, proxy->fds_[1], proxy->target_appid_));
755     DebugPort::GetInst()->AddSession(proxy->port_name_, proxy->target_appid_,
756         proxy->fds_[0], proxy->fds_[1]);
757     listener->OnConnected(proxy->target_appid_, proxy->main_port_.get());
758     _W("target_appid(%s), port_name(%s), main_fd(%d), delegate_fd(%d)",
759         proxy->target_appid_.c_str(), proxy->port_name_.c_str(),
760         proxy->fds_[0], proxy->fds_[1]);
761   } else {
762     proxy->fds_[0] = client_fd;
763     proxy->main_port_.reset(
764         new ProxyPort(proxy, proxy->fds_[0], proxy->target_appid_, false));
765   }
766
767   return G_SOURCE_REMOVE;
768 }
769
770 std::shared_ptr<Proxy> Proxy::GetSharedPtr() {
771   return shared_from_this();
772 }
773
774 gpointer Proxy::CreateWeakPtr() {
775   auto* ptr = new (std::nothrow) std::weak_ptr<Proxy>(GetSharedPtr());
776   return static_cast<gpointer>(ptr);
777 }
778
779 void Proxy::DestroyWeakPtr(gpointer data) {
780   auto* ptr = static_cast<std::weak_ptr<Proxy>*>(data);
781   delete ptr;
782 }
783
784 }  // namespace internal
785 }  // namespace rpc_port