87d68991147e979e590ca61ba1027604216029aa
[platform/framework/web/wrt-commons.git] / modules / rpc / include / dpl / rpc / generic_socket_rpc_server.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_server.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 server
21  */
22 #ifndef DPL_GENERIC_SOCKET_RPC_SERVER_H
23 #define DPL_GENERIC_SOCKET_RPC_SERVER_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 GenericSocketRPCServer
36     : public AbstractRPCConnector,
37       private DPL::Event::EventListener<DPL::Socket::AbstractSocketEvents::AcceptEvent>
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 *> InternalInterfaceSet;
54     InternalInterfaceSet m_internalInterfacesSet;
55
56     virtual void OnEventReceived(const DPL::Socket::AbstractSocketEvents::AcceptEvent &event)
57     {
58         // Retrieve socket sender
59         SocketType *server = static_cast<SocketType *>(event.GetSender());
60
61         // Is this interface still tracked ?
62         // It might have disappeared on close
63         typename InternalInterfaceSet::iterator iterator = m_internalInterfacesSet.find(server);
64
65         if (iterator == m_internalInterfacesSet.end())
66         {
67             LogPedantic("RPC server interface socket disappeared");
68             return;
69         }
70
71         // Accept incoming client
72         SocketType *client = static_cast<SocketType *>(server->Accept());
73         if(client == NULL)
74         {
75             LogPedantic("Spontaneous accept on socket occurred");
76             return;
77         }
78
79         LogPedantic("Client connected to server: " << client->GetRemoteAddress().ToString());
80
81         // Open specific connection implementation
82         AbstractRPCConnection *connection = OpenSpecificConnection(client);
83
84         // Retrieve ID once again
85         AbstractRPCConnectionID connectionID = static_cast<AbstractRPCConnectionID>(server);
86
87         // Inform listeners
88         DPL::Event::EventSupport<AbstractRPCConnectorEvents::ConnectionEstablishedEvent>::
89             EmitEvent(AbstractRPCConnectorEvents::ConnectionEstablishedEvent(
90                 connectionID, connection, EventSender(this)), DPL::Event::EmitMode::Queued);
91     }
92
93 public:
94     explicit GenericSocketRPCServer()
95     {
96     }
97
98     virtual ~GenericSocketRPCServer()
99     {
100         // Always close connection
101         CloseAll();
102     }
103
104     AbstractRPCConnectionID Open(const Address &socketAddress)
105     {
106         LogPedantic("Starting server: " << socketAddress.ToString());
107
108         // Alloc new socket
109         SocketType *socket = new SocketType();
110
111         // Add socket listener
112         socket->EventSupport<DPL::Socket::AbstractSocketEvents::AcceptEvent>::AddListener(this);
113
114         Try
115         {
116             // Open socket
117             socket->Open();
118
119             // Bind socket address
120             socket->Bind(socketAddress);
121
122             // Start listening
123             socket->Listen(8);
124         }
125         Catch (DPL::Socket::AbstractSocket::Exception::Base)
126         {
127             // Remove back socket listener
128             socket->EventSupport<DPL::Socket::AbstractSocketEvents::AcceptEvent>::RemoveListener(this);
129
130             // Log debug
131             LogPedantic("Cannot start server: " << socketAddress.ToString());
132
133             // Problem with server startup
134             ReThrowMsg(typename Exception::OpenFailed, socketAddress.ToString());
135         }
136
137         // Register new internal connection
138         m_internalInterfacesSet.insert(socket);
139
140         // Debug info
141         LogPedantic("Server started on interface: " << socket->GetLocalAddress().ToString());
142
143         // Return unique identifier
144         return static_cast<AbstractRPCConnectionID>(socket);
145     }
146
147     void Close(AbstractRPCConnectionID connectionID)
148     {
149         LogPedantic("Closing server interface...");
150
151         // Get socket from ID
152         SocketType *socket = static_cast<SocketType *>(connectionID);
153
154         // Find corresponding internal connection
155         typename InternalInterfaceSet::iterator iterator = m_internalInterfacesSet.find(socket);
156
157         if (iterator == m_internalInterfacesSet.end())
158             return;
159
160         // Close socket
161         socket->Close();
162
163         // Remove socket listeners
164         socket->EventSupport<DPL::Socket::AbstractSocketEvents::AcceptEvent>::RemoveListener(this);
165         delete socket;
166
167         m_internalInterfacesSet.erase(iterator);
168
169         // Done
170         LogPedantic("Closed");
171     }
172
173     void CloseAll()
174     {
175         while (!m_internalInterfacesSet.empty())
176             Close(static_cast<AbstractRPCConnectionID>(*m_internalInterfacesSet.begin()));
177     }
178 };
179
180 }
181 } // namespace DPL
182
183 #endif // DPL_GENERIC_SOCKET_RPC_SERVER_H