Tizen 2.0 Release
[framework/web/wrt-commons.git] / examples / fake_rpc / fake_rpc.cpp
1 /*
2  * Copyright (c) 2011 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  * @file        rpc.cpp
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @author      Pawel Sikorski (p.sikorski@samsung.com)
20  * @version     1.0
21  * @brief       This file is the implementation file of RPC example
22  */
23 #include <stddef.h>
24 #include <dpl/unix_socket_rpc_client.h>
25 #include <dpl/unix_socket_rpc_server.h>
26 #include <dpl/unix_socket_rpc_connection.h>
27 #include <dpl/fake_rpc_connection.h>
28 #include <memory>
29 #include <dpl/application.h>
30 #include <dpl/controller.h>
31 #include <dpl/thread.h>
32 #include <dpl/log/log.h>
33 #include <string>
34
35 // FLOW:
36 // 1st connection - UnixSockets
37 // 2nd connection - Fake
38 // client sends data via fake IPC
39 // server sends back this data via unix IPC.
40 // client compare sent and received data
41
42 static const char *UNIX_RPC_NAME = "/tmp/unix_socket_rpc";
43 static const char *FAKE_RPC_NAME = "/tmp/fake_rpc";
44
45 typedef DPL::AbstractRPCConnectionEvents::AsyncCallEvent AsyncCallEvent;
46 typedef DPL::AbstractRPCConnectionEvents::ConnectionClosedEvent
47     ConnectionClosedEvent;
48 typedef DPL::AbstractRPCConnectionEvents::ConnectionBrokenEvent
49     ConnectionBrokenEvent;
50 typedef DPL::AbstractRPCConnectorEvents::ConnectionEstablishedEvent
51     ConnectionEstablishedEvent;
52
53 class MyThread
54     : public DPL::Thread,
55       private DPL::EventListener<AsyncCallEvent>,
56       private DPL::EventListener<ConnectionEstablishedEvent>
57 {
58 private:
59     DPL::UnixSocketRPCClient m_rpcUnixClient;
60     DPL::FakeRpcClient m_rpcFakeClient;
61     int m_connections;
62     int m_sentData;
63     int m_receivedData;
64
65     std::unique_ptr<DPL::AbstractRPCConnection> m_rpcUnixConnection;
66     std::unique_ptr<DPL::AbstractRPCConnection> m_rpcFakeConnection;
67
68     virtual void OnEventReceived(const AsyncCallEvent &event)
69     {
70         LogInfo("CLIENT: AsyncCallEvent received");
71
72         event.GetArg0().ConsumeArg(m_receivedData);
73         LogInfo("CLIENT: Result from server: " << m_receivedData);
74
75         if (m_receivedData != m_sentData)
76             LogError("Wrong data Received!");
77     }
78
79     virtual void OnEventReceived(const ConnectionEstablishedEvent &event)
80     {
81         if (dynamic_cast<DPL::FakeRpcConnection *>(event.GetArg1())){
82             ++m_connections;
83             LogInfo("CLIENT: Acquiring new fake connection");
84             m_rpcFakeConnection.reset(event.GetArg1());
85             //this is not used on this side
86 //            m_rpcFakeConnection->DPL::EventSupport<AsyncCallEvent>::AddListener(this);
87         }
88         else{
89             ++m_connections;
90             LogInfo("CLIENT: Acquiring new unix connection");
91             m_rpcUnixConnection.reset(event.GetArg1());
92             m_rpcUnixConnection->DPL::EventSupport<AsyncCallEvent>::AddListener(this);
93         }
94         if(m_connections == 2){
95             m_sentData = 1213;
96             // Emit RPC function call
97             DPL::RPCFunction proc;
98             proc.AppendArg(m_sentData);
99             LogInfo("CLIENT: Calling RPC function");
100             m_rpcFakeConnection->AsyncCall(proc);
101         }
102     }
103
104 public:
105     virtual ~MyThread()
106     {
107         // Always quit thread
108        Quit();
109     }
110
111     virtual int ThreadEntry()
112     {
113         m_connections = 0;
114         // Attach RPC listeners
115         LogInfo("CLIENT: Attaching connection established event");
116         m_rpcUnixClient.DPL::EventSupport<ConnectionEstablishedEvent>::AddListener(this);
117         m_rpcFakeClient.DPL::EventSupport<ConnectionEstablishedEvent>::AddListener(this);
118
119         // Open connection to server
120         LogInfo("CLIENT: Opening connection to RPC");
121         m_rpcUnixClient.Open(UNIX_RPC_NAME);
122         m_rpcFakeClient.Open(FAKE_RPC_NAME);
123
124         // Start message loop
125         LogInfo("CLIENT: Starting thread event loop");
126         int ret = Exec();
127
128         if (m_rpcUnixConnection.get()){
129             LogInfo("CLIENT: Removing Unix connection");
130             m_rpcUnixConnection->DPL::EventSupport<AsyncCallEvent>::RemoveListener(this);
131             m_rpcUnixConnection.reset();
132         }
133
134         LogInfo("CLIENT: Closing");
135
136         if (m_rpcFakeConnection.get()){
137             LogInfo("CLIENT: Removing Fake connection");
138             //this is not used on this side
139 //            m_rpcFakeConnection->DPL::EventSupport<AsyncCallEvent>::RemoveListener(this);
140             m_rpcFakeConnection.reset();
141         }
142
143         // Detach RPC client listener
144         LogInfo("CLIENT: Detaching connection established event");
145         m_rpcUnixClient.DPL::EventSupport<ConnectionEstablishedEvent>::RemoveListener(this);
146         m_rpcFakeClient.DPL::EventSupport<ConnectionEstablishedEvent>::RemoveListener(this);
147
148         // Close RPC
149         LogInfo("CLIENT: Closing RPC client");
150         m_rpcUnixClient.CloseAll();
151         m_rpcFakeClient.Close();//not needed
152
153         // Done
154         return ret;
155     }
156 };
157
158 DECLARE_GENERIC_EVENT_0(QuitEvent)
159 DECLARE_GENERIC_EVENT_0(CloseThreadEvent)
160
161 class MyApplication
162     : public DPL::Application,
163       private DPL::Controller<DPL::TypeListDecl<QuitEvent,
164                                                 CloseThreadEvent>::Type>,
165       private DPL::EventListener<AsyncCallEvent>,
166       private DPL::EventListener<ConnectionEstablishedEvent>
167 {
168 private:
169     DPL::UnixSocketRPCServer m_rpcUnixServer;
170     DPL::FakeRpcServer m_rpcFakeServer;
171
172     std::unique_ptr<DPL::AbstractRPCConnection> m_rpcUnixConnection;
173     std::unique_ptr<DPL::AbstractRPCConnection> m_rpcFakeConnection;
174
175     MyThread m_thread;
176
177     // Quit application event occurred
178     virtual void OnEventReceived(const QuitEvent &/*event*/){
179         // Close RPC now
180         LogInfo("SERVER: Closing RPC connection...");
181
182         // Detach RPC connection listeners
183         if (m_rpcUnixConnection.get()) {
184             //this is not used on this side
185 //            m_rpcUnixConnection->DPL::EventSupport<AsyncCallEvent>::RemoveListener(this);
186             m_rpcUnixConnection.reset();
187         }
188
189         if (m_rpcFakeConnection.get()) {
190             m_rpcFakeConnection->DPL::EventSupport<AsyncCallEvent>::RemoveListener(this);
191             m_rpcFakeConnection.reset();
192         }
193
194         LogInfo("SERVER: Closing Server");
195         m_rpcUnixServer.CloseAll();
196         m_rpcFakeServer.CloseAll();//not needed
197         m_rpcUnixServer.DPL::EventSupport<ConnectionEstablishedEvent>::RemoveListener(this);
198         m_rpcFakeServer.DPL::EventSupport<ConnectionEstablishedEvent>::RemoveListener(this);
199
200         LogInfo("SERVER: Server closed");
201
202         Quit();
203     }
204
205     virtual void OnEventReceived(const CloseThreadEvent &/*event*/){
206         m_thread.Quit();
207     }
208
209     virtual void OnEventReceived(const AsyncCallEvent &event)
210     {
211         LogInfo("SERVER: AsyncCallEvent received");
212
213         int value;
214         event.GetArg0().ConsumeArg(value);
215         LogInfo("SERVER: Result from client: " << value);
216
217         // send back data to client (via fake)
218         // Emit RPC function call
219         DPL::RPCFunction proc;
220         proc.AppendArg(value);
221         LogInfo("SERVER: Calling RPC function");
222         m_rpcUnixConnection->AsyncCall(proc);
223     }
224
225     virtual void OnEventReceived(const ConnectionEstablishedEvent &event)
226     {
227         // Save connection pointer
228         if (dynamic_cast<DPL::FakeRpcConnection *>(event.GetArg1())){
229             LogInfo("SERVER: Acquiring Fake RPC connection");
230             m_rpcFakeConnection.reset(event.GetArg1());
231             m_rpcFakeConnection->DPL::EventSupport<AsyncCallEvent>::AddListener(this);
232         }
233         else{
234             LogInfo("SERVER: Acquiring Unix RPC connection");
235             m_rpcUnixConnection.reset(event.GetArg1());
236             //this is not used on this side
237 //            m_rpcUnixConnection->DPL::EventSupport<AsyncCallEvent>::AddListener(this);
238         }
239     }
240
241 public:
242     MyApplication(int argc, char **argv)
243         : Application(argc, argv, "rpc")
244     {
245         // Attach RPC server listeners
246         LogInfo("SERVER: Attaching connection established event");
247         m_rpcUnixServer.DPL::EventSupport<ConnectionEstablishedEvent>::AddListener(this);
248         m_rpcFakeServer.DPL::EventSupport<ConnectionEstablishedEvent>::AddListener(this);
249
250         // Self touch
251         LogInfo("SERVER: Touching controller");
252         Touch();
253
254         // Open RPC server
255         LogInfo("SERVER: Opening server RPC");
256         m_rpcUnixServer.Open(UNIX_RPC_NAME);
257         m_rpcFakeServer.Open(FAKE_RPC_NAME);
258
259         // Run RPC client in thread
260         LogInfo("SERVER: Starting RPC client thread");
261         m_thread.Run();
262
263         // Quit application automatically in few seconds
264         LogInfo("SERVER: Sending control timed events");
265         DPL::ControllerEventHandler<CloseThreadEvent>::PostTimedEvent(CloseThreadEvent(), 2);
266         DPL::ControllerEventHandler<QuitEvent>::PostTimedEvent(QuitEvent(), 3);
267     }
268
269     virtual ~MyApplication()
270     {
271         // Quit thread
272         LogInfo("SERVER: Quitting thread");
273     }
274 };
275
276 int main(int argc, char *argv[])
277 {
278     LogInfo("Starting");
279     MyApplication app(argc, argv);
280     return app.Exec();
281 }