Initialize Tizen 2.3
[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 namespace RPC {
31 template<typename SocketType>
32 class GenericSocketRPCServer :
33     public AbstractRPCConnector,
34     private DPL::Event::EventListener<DPL::Socket::AbstractSocketEvents::
35                                           AcceptEvent>
36 {
37   public:
38     class Exception
39     {
40       public:
41         DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
42         DECLARE_EXCEPTION_TYPE(Base, OpenFailed)
43         DECLARE_EXCEPTION_TYPE(Base, CloseFailed)
44     };
45
46   protected:
47     // Derived class implementations for connection managment
48     virtual AbstractRPCConnection *OpenSpecificConnection(SocketType *socket) =
49         0;
50
51   private:
52     typedef std::set<SocketType *> InternalInterfaceSet;
53     InternalInterfaceSet m_internalInterfacesSet;
54
55     virtual void OnEventReceived(
56         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 =
64             m_internalInterfacesSet.find(server);
65
66         if (iterator == m_internalInterfacesSet.end()) {
67             WrtLogD("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             WrtLogD("Spontaneous accept on socket occurred");
75             return;
76         }
77
78         WrtLogD("Client connected to server: %s",
79                 client->GetRemoteAddress().ToString().c_str());
80
81         // Open specific connection implementation
82         AbstractRPCConnection *connection = OpenSpecificConnection(client);
83
84         // Retrieve ID once again
85         AbstractRPCConnectionID connectionID =
86             static_cast<AbstractRPCConnectionID>(server);
87
88         // Inform listeners
89         DPL::Event::EventSupport<AbstractRPCConnectorEvents::
90                                      ConnectionEstablishedEvent>::
91             EmitEvent(AbstractRPCConnectorEvents::ConnectionEstablishedEvent(
92                           connectionID, connection, EventSender(
93                               this)), DPL::Event::EmitMode::Queued);
94     }
95
96   public:
97     explicit GenericSocketRPCServer()
98     {}
99
100     virtual ~GenericSocketRPCServer()
101     {
102         // Always close connection
103         CloseAll();
104     }
105
106     AbstractRPCConnectionID Open(const Address &socketAddress)
107     {
108         WrtLogD("Starting server: %s", socketAddress.ToString().c_str());
109
110         // Alloc new socket
111         SocketType *socket = new SocketType();
112
113         // Add socket listener
114         socket->EventSupport<DPL::Socket::AbstractSocketEvents::AcceptEvent>::
115             AddListener(this);
116
117         Try
118         {
119             // Open socket
120             socket->Open();
121
122             // Bind socket address
123             socket->Bind(socketAddress);
124
125             // Start listening
126             socket->Listen(8);
127         }
128         Catch(DPL::Socket::AbstractSocket::Exception::Base)
129         {
130             // Remove back socket listener
131             socket->EventSupport<DPL::Socket::AbstractSocketEvents::AcceptEvent>
132                 ::RemoveListener(this);
133
134             // Log debug
135             WrtLogD("Cannot start server: %s", socketAddress.ToString().c_str());
136
137             // Problem with server startup
138             ReThrowMsg(typename Exception::OpenFailed, socketAddress.ToString());
139         }
140
141         // Register new internal connection
142         m_internalInterfacesSet.insert(socket);
143
144         // Debug info
145         WrtLogD("Server started on interface: %s",
146                 socket->GetLocalAddress().ToString().c_str());
147
148         // Return unique identifier
149         return static_cast<AbstractRPCConnectionID>(socket);
150     }
151
152     void Close(AbstractRPCConnectionID connectionID)
153     {
154         WrtLogD("Closing server interface...");
155
156         // Get socket from ID
157         SocketType *socket = static_cast<SocketType *>(connectionID);
158
159         // Find corresponding internal connection
160         typename InternalInterfaceSet::iterator iterator =
161             m_internalInterfacesSet.find(socket);
162
163         if (iterator == m_internalInterfacesSet.end()) {
164             return;
165         }
166
167         // Close socket
168         socket->Close();
169
170         // Remove socket listeners
171         socket->EventSupport<DPL::Socket::AbstractSocketEvents::AcceptEvent>::
172             RemoveListener(this);
173         delete socket;
174
175         m_internalInterfacesSet.erase(iterator);
176
177         // Done
178         WrtLogD("Closed");
179     }
180
181     void CloseAll()
182     {
183         while (!m_internalInterfacesSet.empty()) {
184             Close(static_cast<AbstractRPCConnectionID>(*m_internalInterfacesSet
185                                                            .begin()));
186         }
187     }
188 };
189 }
190 } // namespace DPL
191
192 #endif // DPL_GENERIC_SOCKET_RPC_SERVER_H