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 //------------------------------------------------------------------------------ 44 Server::Server( 45 ConnectionHandler *connectionHandler, 46 const char *localAddr 47 ) : socketAddr(localAddr) 48 { 49 this->connectionHandler = connectionHandler; 50 } 51 52 53 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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 //------------------------------------------------------------------------------ 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