14e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park/** @addtogroup MCD_MCDIMPL_DAEMON_SRV
24e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * @{
34e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * @file
44e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *
54e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * Connection server.
64e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *
74e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * Handles incoming socket connections from clients using the MobiCore driver.
84e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *
94e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * <!-- Copyright Giesecke & Devrient GmbH 2009 - 2012 -->
107b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim *
114e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * Redistribution and use in source and binary forms, with or without
124e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * modification, are permitted provided that the following conditions
134e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * are met:
144e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 1. Redistributions of source code must retain the above copyright
154e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *    notice, this list of conditions and the following disclaimer.
164e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 2. Redistributions in binary form must reproduce the above copyright
174e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *    notice, this list of conditions and the following disclaimer in the
184e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *    documentation and/or other materials provided with the distribution.
194e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * 3. The name of the author may not be used to endorse or promote
204e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *    products derived from this software without specific prior
214e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *    written permission.
224e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park *
234e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
244e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
254e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
264e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
274e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
284e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
294e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
304e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
314e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
324e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
334e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
344e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park */
354e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include "public/NetlinkServer.h"
364e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <unistd.h>
374e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <string.h>
384e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <errno.h>
394e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <linux/netlink.h>
404e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
414e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <stdlib.h>
424e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include "NetlinkConnection.h"
434e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include <signal.h>
444e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
457b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim#define LOG_TAG "McDaemon"
464e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park#include "log.h"
474e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
484e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
494e9e8c9c0169b40318386436d762c3d73cf4c328DongJin ParkNetlinkServer::NetlinkServer(
507b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    ConnectionHandler *connectionHandler
517b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim): Server(connectionHandler, "dummy")
527b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
534e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
544e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
554e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
564e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
574e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Parkvoid NetlinkServer::run(
587b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
597b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
607b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    do {
617b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        LOG_I("NetlinkServer: Starting to listen on netlink bus");
627b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
637b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // Open a socket
647b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        serverSock = socket(PF_NETLINK, SOCK_DGRAM,  MC_DAEMON_NETLINK);
657b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        if (serverSock < 0) {
667b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            LOG_ERRNO("Opening socket");
677b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            break;
687b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
697b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
707b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // Fill in address structure and bind to socket
717b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        struct sockaddr_nl src_addr;
727b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        struct nlmsghdr *nlh = NULL;
737b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        struct iovec iov;
747b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        struct msghdr msg;
757b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        uint32_t len;
767b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
777b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        memset(&src_addr, 0, sizeof(src_addr));
787b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        src_addr.nl_family = AF_NETLINK;
797b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        src_addr.nl_pid = MC_DAEMON_PID;  /* daemon pid */
807b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        src_addr.nl_groups = 0;  /* not in mcast groups */
817b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        if (bind(serverSock, (struct sockaddr *)&src_addr, sizeof(src_addr)) < 0) {
829081ca65cb7959b6a06ba44823f84a6afa8bca2fJihyun Kim            LOG_ERRNO("Binding to server socket failed, because bind");
837b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            close(serverSock);
847b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            break;
857b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
867b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
877b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // Start reading the socket
887b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        LOG_I("\n********* successfully initialized *********\n");
897b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
907b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        for (;;) {
917b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // This buffer will be taken over by the connection it was routed to
927b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
937b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            memset(&msg, 0, sizeof(msg));
947b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            iov.iov_base = (void *)nlh;
957b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            iov.iov_len = NLMSG_SPACE(MAX_PAYLOAD);
967b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            msg.msg_iov = &iov;
977b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            msg.msg_iovlen = 1;
987b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            msg.msg_name = &src_addr;
997b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            msg.msg_namelen = sizeof(src_addr);
1007b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1017b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            memset(nlh, 0, NLMSG_SPACE(MAX_PAYLOAD));
1027b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1037b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // Read the incomming message and route it to the connection based
1047b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // on the incomming PID
1057b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            if ((len = recvmsg(serverSock, &msg, 0)) < 0) {
1067b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                LOG_ERRNO("recvmsg");
1077b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                break;
1087b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            }
1097b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1104e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park            if (NLMSG_OK(nlh, len)) {
1117b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                handleMessage(nlh);
1127b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            } else {
1137b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                break;
1147b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            }
1157b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
1167b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    } while (false);
1177b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1187b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    LOG_ERRNO("Exiting NetlinkServer! Because it");
1194e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
1204e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1214e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
1224e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Parkvoid NetlinkServer::handleMessage(
1234e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park    struct nlmsghdr *nlh
1247b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
1257b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
1267b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    uint32_t seq = nlh->nlmsg_seq;
1277b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    uint32_t pid = nlh->nlmsg_pid;
1287b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    //LOG_I("%s: Handling NQ message for pid %u seq %u...", __FUNCTION__, pid, seq);
1297b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    uint64_t hash = hashConnection(pid, seq);
1307b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    /* First cleanup the connection list */
1317b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    cleanupConnections();
1327b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1337b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    NetlinkConnection *connection = findConnection(hash);
1347b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    // This is a message from a new client
1357b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    if (connection == NULL) {
1367b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        //LOG_I("%s: Cound't find the connection, creating a new one", __FUNCTION__);
1377b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        connection = new NetlinkConnection(this, serverSock, pid, seq);
1387b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // Add the new connection
1397b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        insertConnection(hash, connection);
1407b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    }
1417b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1427b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    connection->handleMessage(nlh);
1437b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1447b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    // Only handle connections which have not been detached
1457b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    if (connection->detached == false) {
1467b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        if (!connectionHandler->handleConnection(connection)) {
1477b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            LOG_I("%s: No command processed.", __FUNCTION__);
1487b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            connection->socketDescriptor = -1;
1497b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            //Inform the driver
1507b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            connectionHandler->dropConnection(connection);
1517b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1527b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // Remove connection from list
1537b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            removeConnection(hash);
1547b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            connection->socketDescriptor = -1;
1557b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            delete connection;
1567b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
1577b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // If connection data is set to NULL then device close has been called
1587b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // so we must remove all connections associated with this hash
1597b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        else if (connection->connectionData == NULL &&
1607b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                 connection->detached == false) {
1617b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            delete connection;
1627b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
1637b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    }
1644e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
1654e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1664e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1674e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
1684e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Parkvoid NetlinkServer::detachConnection(
1694e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park    Connection *connection
1707b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
1717b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
1727b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    connection->detached = true;
1734e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
1744e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1754e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1764e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
1774e9e8c9c0169b40318386436d762c3d73cf4c328DongJin ParkNetlinkServer::~NetlinkServer(
1787b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    void
1797b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
1807b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
1817b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    connectionMap_t::iterator i;
1827b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    // Shut down the server socket
1837b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    close(serverSock);
1847b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
1857b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    // Destroy all client connections
1867b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    for (i = peerConnections.begin(); i != peerConnections.end(); i++) {
1877b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        if (i->second->detached == false) {
1887b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            delete i->second;
1897b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
1907b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    }
1917b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    peerConnections.clear();
1924e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
1934e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1944e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
1954e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
1967b143edf281bed18c8ebd0733465f3af5af327ebJungtae KimNetlinkConnection *NetlinkServer::findConnection(
1974e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park    uint64_t hash
1987b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
1997b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
2007b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    connectionMap_t::iterator i = peerConnections.find(hash);
2017b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    if (i != peerConnections.end()) {
2027b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        return i->second;
2037b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    }
2044e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
2057b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    return NULL;
2064e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
2074e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
2084e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
2094e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
2104e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Parkvoid NetlinkServer::insertConnection(
2117b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    uint64_t hash,
2124e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park    NetlinkConnection *connection
2137b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
2147b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
2157b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    peerConnections[hash] = connection;
2164e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
2174e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
2184e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park/* This is called from multiple threads! */
2194e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
2204e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Parkvoid NetlinkServer::removeConnection(
2217b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    uint64_t hash
2227b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
2237b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
2247b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    connectionMap_t::iterator i = peerConnections.find(hash);
2257b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    if (i != peerConnections.end()) {
2267b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        peerConnections.erase(i);
2277b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    }
2284e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
2294e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
2304e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park//------------------------------------------------------------------------------
2314e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Parkvoid NetlinkServer::cleanupConnections(
2327b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    void
2337b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim)
2347b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim{
2357b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    connectionMap_t::reverse_iterator i;
2367b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    pid_t pid;
2377b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    NetlinkConnection *connection = NULL;
2387b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    // Destroy all client connections
2397b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    for (i = peerConnections.rbegin(); i != peerConnections.rend(); ++i) {
2407b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        connection = i->second;
2417b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // Only 16 bits are for the actual PID, the rest is session magic
2427b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        pid = connection->peerPid & 0xFFFF;
2437b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        //LOG_I("%s: checking PID %u", __FUNCTION__, pid);
2447b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        // Check if the peer pid is still alive
2457b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        if (pid == 0) {
2467b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            continue;
2477b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
2487b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        if (kill(pid, 0)) {
2497b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            bool detached = connection->detached;
2507b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            LOG_I("%s: PID %u has died, cleaning up session 0x%X",
2517b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                  __FUNCTION__, pid, connection->peerPid);
2527b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
2537b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            connection->socketDescriptor = -1;
2547b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            //Inform the driver
2557b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            connectionHandler->dropConnection(connection);
2567b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
2577b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // We aren't handling this connection anymore no matter what
2587b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            removeConnection(connection->hash);
2597b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim
2607b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // Remove connection from list only if detached, the detached
2617b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            // connections are managed by the device
2627b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            if (detached == false) {
2637b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                delete connection;
2647b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            }
2657b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            if (peerConnections.size() == 0) {
2667b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim                break;
2677b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            }
2687b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim            i = peerConnections.rbegin();
2697b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim        }
2707b143edf281bed18c8ebd0733465f3af5af327ebJungtae Kim    }
2714e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park}
2724e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park
2734e9e8c9c0169b40318386436d762c3d73cf4c328DongJin Park/** @} */
274