2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file generic_socket_rpc_client.h
18 * @author Przemyslaw Dobrowolski (p.dobrowolsk@samsung.com)
20 * @brief This file is the header file for generic socket RPC client
22 #ifndef DPL_GENERIC_SOCKET_RPC_CLIENT_H
23 #define DPL_GENERIC_SOCKET_RPC_CLIENT_H
25 #include <dpl/rpc/abstract_rpc_connector.h>
26 #include <dpl/socket/abstract_socket.h>
34 template<typename SocketType>
35 class GenericSocketRPCClient
36 : public AbstractRPCConnector,
37 private DPL::Event::EventListener<DPL::Socket::AbstractSocketEvents::ConnectedEvent>
43 DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
44 DECLARE_EXCEPTION_TYPE(Base, OpenFailed)
45 DECLARE_EXCEPTION_TYPE(Base, CloseFailed)
49 // Derived class implementations for connection managment
50 virtual AbstractRPCConnection *OpenSpecificConnection(SocketType *socket) = 0;
53 typedef std::set<SocketType *> InternalConnectionSet;
54 InternalConnectionSet m_internalConnectionSet;
56 virtual void OnEventReceived(const DPL::Socket::AbstractSocketEvents::ConnectedEvent &event)
58 // Retrieve socket sender
59 SocketType *socket = static_cast<SocketType *>(event.GetSender());
61 LogPedantic("Connection with RPC server established");
63 // Is this connection still tracked ?
64 // It might have disappeared on close
65 typename InternalConnectionSet::iterator iterator = m_internalConnectionSet.find(socket);
67 if (iterator == m_internalConnectionSet.end())
69 LogPedantic("RPC client connection socket disappeared");
73 // Open specific connection implementation
74 AbstractRPCConnection *connection = OpenSpecificConnection(socket);
76 // Remove internal connection
77 socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::RemoveListener(this);
78 m_internalConnectionSet.erase(iterator);
80 // Retrieve ID once again
81 AbstractRPCConnectionID connectionID = static_cast<AbstractRPCConnectionID>(socket);
84 DPL::Event::EventSupport<AbstractRPCConnectorEvents::ConnectionEstablishedEvent>::
85 EmitEvent(AbstractRPCConnectorEvents::ConnectionEstablishedEvent(
86 connectionID, connection, EventSender(this)), DPL::Event::EmitMode::Queued);
90 explicit GenericSocketRPCClient()
94 virtual ~GenericSocketRPCClient()
96 // Always close all connections
100 AbstractRPCConnectionID Open(const Address &socketAddress)
102 LogPedantic("Starting client: " << socketAddress.ToString());
105 SocketType *socket = new SocketType();
107 // Add socket listeners
108 socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::AddListener(this);
115 // Start connecting to server
116 socket->Connect(Address(socketAddress));
118 Catch (DPL::Socket::AbstractSocket::Exception::Base)
120 // Remove back socket listener
121 socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::RemoveListener(this);
124 LogPedantic("Cannot connect to: " << socketAddress.ToString());
126 // Problem with client startup
127 ReThrowMsg(typename Exception::OpenFailed, socketAddress.ToString());
130 // Register new internal connection
131 m_internalConnectionSet.insert(socket);
134 LogPedantic("Client started on interface: " << socket->GetLocalAddress().ToString());
136 // Return unique identifier
137 return static_cast<AbstractRPCConnectionID>(socket);
140 void Close(AbstractRPCConnectionID connectionID)
142 LogPedantic("Closing client interface...");
144 // Get socket from ID
145 SocketType *socket = static_cast<SocketType *>(connectionID);
147 // Find corresponding internal connection
148 typename InternalConnectionSet::iterator iterator = m_internalConnectionSet.find(socket);
150 if (iterator == m_internalConnectionSet.end())
156 // Remove internal socket
157 socket->EventSupport<DPL::Socket::AbstractSocketEvents::ConnectedEvent>::RemoveListener(this);
160 m_internalConnectionSet.erase(iterator);
163 LogPedantic("Closed");
168 while (!m_internalConnectionSet.empty())
169 Close(static_cast<AbstractRPCConnectionID>(*m_internalConnectionSet.begin()));
176 #endif // DPL_GENERIC_SOCKET_RPC_CLIENT_H