1 /** @addtogroup MCD_MCDIMPL_DAEMON_SRV
2 * @{
3 * @file
4 *
5 * Connection server.
6 *
7 * Handles incoming socket connections from clients using the MobiCore driver.
8 *
9 * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote
20 * products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
24 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
29 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 #include "public/Server.h"
36 #include <unistd.h>
37 #include <string.h>
38 #include <errno.h>
39
40 //#define LOG_VERBOSE
41 #include "log.h"
42
43 //------------------------------------------------------------------------------
Server(ConnectionHandler * connectionHandler,const char * localAddr)44 Server::Server(
45 ConnectionHandler *connectionHandler,
46 const char *localAddr
47 ) : socketAddr(localAddr)
48 {
49 this->connectionHandler = connectionHandler;
50 }
51
52
53 //------------------------------------------------------------------------------
run(void)54 void Server::run(
55 void
56 )
57 {
58 do {
59 LOG_I("Server: start listening on socket %s", socketAddr.c_str());
60
61 // Open a socket (a UNIX domain stream socket)
62 serverSock = socket(AF_UNIX, SOCK_STREAM, 0);
63 if (serverSock < 0) {
64 LOG_ERRNO("Can't open stream socket, because socket");
65 break;
66 }
67
68 // Fill in address structure and bind to socket
69 struct sockaddr_un serverAddr;
70 serverAddr.sun_family = AF_UNIX;
71 strncpy(serverAddr.sun_path, socketAddr.c_str(), sizeof(serverAddr.sun_path) - 1);
72
73 uint32_t len = strlen(serverAddr.sun_path) + sizeof(serverAddr.sun_family);
74 // Make the socket in the Abstract Domain(no path but everyone can connect)
75 serverAddr.sun_path[0] = 0;
76 if (bind(serverSock, (struct sockaddr *) &serverAddr, len) < 0) {
77 LOG_ERRNO("Binding to server socket failed, because bind");
78 }
79
80 // Start listening on the socket
81 if (listen(serverSock, LISTEN_QUEUE_LEN) < 0) {
82 LOG_ERRNO("listen");
83 break;
84 }
85
86 LOG_I("\n********* successfully initialized Daemon *********\n");
87
88 for (;;) {
89 fd_set fdReadSockets;
90
91 // Clear FD for select()
92 FD_ZERO(&fdReadSockets);
93
94 // Select server socket descriptor
95 FD_SET(serverSock, &fdReadSockets);
96 int maxSocketDescriptor = serverSock;
97
98 // Select socket descriptor of all connections
99 for (connectionIterator_t iterator = peerConnections.begin();
100 iterator != peerConnections.end();
101 ++iterator) {
102 Connection *connection = (*iterator);
103 int peerSocket = connection->socketDescriptor;
104 FD_SET(peerSocket, &fdReadSockets);
105 if (peerSocket > maxSocketDescriptor) {
106 maxSocketDescriptor = peerSocket;
107 }
108 }
109
110 // Wait for activities, select() returns the number of sockets
111 // which require processing
112 LOG_V(" Server: waiting on sockets");
113 int numSockets = select(
114 maxSocketDescriptor + 1,
115 &fdReadSockets,
116 NULL, NULL, NULL);
117
118 // Check if select failed
119 if (numSockets < 0) {
120 LOG_ERRNO("select");
121 break;
122 }
123
124 // actually, this should not happen.
125 if (0 == numSockets) {
126 LOG_W(" Server: select() returned 0, spurious event?.");
127 continue;
128 }
129
130 LOG_V(" Server: events on %d socket(s).", numSockets);
131
132 // Check if a new client connected to the server socket
133 if (FD_ISSET(serverSock, &fdReadSockets)) {
134 do {
135 LOG_V(" Server: new connection attempt.");
136 numSockets--;
137
138 struct sockaddr_un clientAddr;
139 socklen_t clientSockLen = sizeof(clientAddr);
140 int clientSock = accept(
141 serverSock,
142 (struct sockaddr *) &clientAddr,
143 &clientSockLen);
144
145 if (clientSock <= 0) {
146 LOG_ERRNO("accept");
147 break;
148 }
149
150 Connection *connection = new Connection(clientSock, &clientAddr);
151 peerConnections.push_back(connection);
152 LOG_I(" Server: new socket connection established and start listening.");
153 } while (false);
154
155 // we can ignore any errors from accepting a new connection.
156 // If this fail, the client has to deal with it, we are done
157 // and nothing has changed.
158 }
159
160 // Handle traffic on existing client connections
161 connectionIterator_t iterator = peerConnections.begin();
162 while ( (iterator != peerConnections.end())
163 && (numSockets > 0) ) {
164 Connection *connection = (*iterator);
165 int peerSocket = connection->socketDescriptor;
166
167 if (!FD_ISSET(peerSocket, &fdReadSockets)) {
168 ++iterator;
169 continue;
170 }
171
172 numSockets--;
173
174 // the connection will be terminated if command processing
175 // fails
176 if (!connectionHandler->handleConnection(connection)) {
177 LOG_I(" Server: dropping connection.");
178
179 //Inform the driver
180 connectionHandler->dropConnection(connection);
181
182 // Remove connection from list
183 delete connection;
184 iterator = peerConnections.erase(iterator);
185 continue;
186 }
187
188 ++iterator;
189 }
190 }
191
192 } while (false);
193
194 LOG_ERRNO("Exiting Server, because");
195 }
196
197
198 //------------------------------------------------------------------------------
detachConnection(Connection * connection)199 void Server::detachConnection(
200 Connection *connection
201 )
202 {
203 LOG_V(" Stopping to listen on notification socket.");
204
205 for (connectionIterator_t iterator = peerConnections.begin();
206 iterator != peerConnections.end();
207 ++iterator) {
208 Connection *tmpConnection = (*iterator);
209 if (tmpConnection == connection) {
210 peerConnections.erase(iterator);
211 LOG_I(" Stopped listening on notification socket.");
212 break;
213 }
214 }
215 }
216
217
218 //------------------------------------------------------------------------------
~Server(void)219 Server::~Server(
220 void
221 )
222 {
223 // Shut down the server socket
224 close(serverSock);
225
226 // Destroy all client connections
227 connectionIterator_t iterator = peerConnections.begin();
228 while (iterator != peerConnections.end()) {
229 Connection *tmpConnection = (*iterator);
230 delete tmpConnection;
231 iterator = peerConnections.erase(iterator);
232 }
233 }
234
235 /** @} */
236