Update User Agent String
[framework/web/wrt-commons.git] / modules / rpc / include / dpl / rpc / generic_socket_rpc_client.h
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        generic_socket_rpc_client.h
18  * @author      Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
19  * @version     1.0
20  * @brief       This file is the header file for generic socket RPC client
21  */
22 #ifndef DPL_GENERIC_SOCKET_RPC_CLIENT_H
23 #define DPL_GENERIC_SOCKET_RPC_CLIENT_H
24
25 #include <dpl/rpc/abstract_rpc_connector.h>
26 #include <dpl/socket/abstract_socket.h>
27 #include <set>
28
29 namespace DPL
30 {
31 namespace RPC
32 {
33
34 template<typename SocketType>
35 class GenericSocketRPCClient
36     : public AbstractRPCConnector,
37       private DPL::Event::EventListener<DPL::Socket::AbstractSocketEvents::ConnectedEvent>
38 {
39 public:
40     class Exception
41     {
42     public:
43         DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
44         DECLARE_EXCEPTION_TYPE(Base, OpenFailed)
45         DECLARE_EXCEPTION_TYPE(Base, CloseFailed)
46     };
47
48 protected:
49     // Derived class implementations for connection managment
50     virtual AbstractRPCConnection *OpenSpecificConnection(SocketType *socket) = 0;
51
52 private:
53     typedef std::set<SocketType *> InternalConnectionSet;
54     InternalConnectionSet m_internalConnectionSet;
55
56     virtual void OnEventReceived(const DPL::Socket::AbstractSocketEvents::ConnectedEvent &event)
57     {
58         // Retrieve socket sender
59         SocketType *socket = static_cast<SocketType *>(event.GetSender());
60
61         LogPedantic("Connection with RPC server established");
62
63         // Is this connection still tracked ?
64         // It might have disappeared on close
65         typename InternalConnectionSet::iterator iterator = m_internalConnectionSet.find(socket);
66
67         if (iterator == m_internalConnectionSet.end())
68         {
69             LogPedantic("RPC client connection socket disappeared");
70             return;
71         }
72
73         // Open specific connection implementation
74         AbstractRPCConnection *connection = OpenSpecificConnection(socket);
75
76         // Remove internal connection
77         socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::RemoveListener(this);
78         m_internalConnectionSet.erase(iterator);
79
80         // Retrieve ID once again
81         AbstractRPCConnectionID connectionID = static_cast<AbstractRPCConnectionID>(socket);
82
83         // Inform listeners
84         DPL::Event::EventSupport<AbstractRPCConnectorEvents::ConnectionEstablishedEvent>::
85             EmitEvent(AbstractRPCConnectorEvents::ConnectionEstablishedEvent(
86                 connectionID, connection, EventSender(this)), DPL::Event::EmitMode::Queued);
87     }
88
89 public:
90     explicit GenericSocketRPCClient()
91     {
92     }
93
94     virtual ~GenericSocketRPCClient()
95     {
96         // Always close all connections
97         CloseAll();
98     }
99
100     AbstractRPCConnectionID Open(const Address &socketAddress)
101     {
102         LogPedantic("Starting client: " << socketAddress.ToString());
103
104         // Alloc new socket
105         SocketType *socket = new SocketType();
106
107         // Add socket listeners
108         socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::AddListener(this);
109
110         Try
111         {
112             // Open socket
113             socket->Open();
114
115             // Start connecting to server
116             socket->Connect(Address(socketAddress));
117         }
118         Catch (DPL::Socket::AbstractSocket::Exception::Base)
119         {
120             // Remove back socket listener
121             socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::RemoveListener(this);
122
123             // Log debug message
124             LogPedantic("Cannot connect to: " << socketAddress.ToString());
125
126             // Problem with client startup
127             ReThrowMsg(typename Exception::OpenFailed, socketAddress.ToString());
128         }
129
130         // Register new internal connection
131         m_internalConnectionSet.insert(socket);
132
133         // Debug info
134         LogPedantic("Client started on interface: " << socket->GetLocalAddress().ToString());
135
136         // Return unique identifier
137         return static_cast<AbstractRPCConnectionID>(socket);
138     }
139
140     void Close(AbstractRPCConnectionID connectionID)
141     {
142         LogPedantic("Closing client interface...");
143
144         // Get socket from ID
145         SocketType *socket = static_cast<SocketType *>(connectionID);
146
147         // Find corresponding internal connection
148         typename InternalConnectionSet::iterator iterator = m_internalConnectionSet.find(socket);
149
150         if (iterator == m_internalConnectionSet.end())
151             return;
152
153         // Close socket
154         socket->Close();
155
156         // Remove internal socket
157         socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::RemoveListener(this);
158         delete socket;
159
160         m_internalConnectionSet.erase(iterator);
161
162         // Done
163         LogPedantic("Closed");
164     }
165
166     void CloseAll()
167     {
168         while (!m_internalConnectionSet.empty())
169             Close(static_cast<AbstractRPCConnectionID>(*m_internalConnectionSet.begin()));
170     }
171 };
172
173 }
174 } // namespace DPL
175
176 #endif // DPL_GENERIC_SOCKET_RPC_CLIENT_H