Merge "Alarm Conditional AppLaunch Refactoring" into tizen_2.2
[platform/framework/native/appfw.git] / src / io / FIo_IpcClient.cpp
index 1b788bc..ef638b2 100644 (file)
@@ -1,5 +1,4 @@
 //
-// Open Service Platform
 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the License);
@@ -59,7 +58,6 @@ _IpcClient::_IpcClient(void)
        : __pReverseSource(null)
        , __fdCount(0)
        , __pFdLock(null)
-       , __name("")
        , __pListener(null)
 {
        __messageBuffer[0] = '\0';
@@ -117,7 +115,7 @@ _IpcClient::Construct(const String& name, const _IIpcClientEventListener* pListe
        return E_SUCCESS;
 
 CATCH:
-       __name = "";
+       __name.Clear();
        __pListener = null;
        __pFdLock = null;
 
@@ -126,12 +124,17 @@ CATCH:
        return r;
 }
 
+String
+_IpcClient::GetName(void) const
+{
+       return __name;
+}
+
 struct HelloMessage
 {
        int pid;
        bool reverse;
        char appId[256];
-       char appExecutableName[256];
 };
 
 result
@@ -143,14 +146,22 @@ _IpcClient::MakeConnection(bool forReverse)
        socklen_t serverLen = 0;
        int client = -1;
        int ret = 0;
-       HelloMessage helloMessage = {0, false};
+       int retry = 0;
+       HelloMessage helloMessage = {0, 0};
        std::string socketName;
        char* pSocketName = null;
        size_t socketNameLength = 0;
        int flags = 0;
 
        helloMessage.pid = getpid();
-       helloMessage.reverse = forReverse;
+       if (forReverse)
+       {
+               helloMessage.reverse = 1;
+       }
+       else
+       {
+               helloMessage.reverse = 0;
+       }
 
        pSocketName = _StringConverter::CopyToCharArrayN(__name);
        SysTryReturnResult(NID_IO, pSocketName != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
@@ -166,7 +177,7 @@ _IpcClient::MakeConnection(bool forReverse)
        if (__fdCount == 0)
        {
                // Set an appId
-               String appId = _AppInfo::GetAppId();
+               String appId = _AppInfo::GetApplicationId();
                int length = (appId.GetLength() + 1) * sizeof(wchar_t);
                if (length > 255)
                {
@@ -176,21 +187,6 @@ _IpcClient::MakeConnection(bool forReverse)
                SysTryReturnResult(NID_IO, appId.GetLength() > 0, E_SYSTEM, "AppId dose not exist.");
 
                memcpy(helloMessage.appId, appId.GetPointer(), length);
-
-               // Set an executableName
-               //String appExecutableName = _PackageManagerImpl::GetInstance()->GetDefaultAppExecutableName(appId);
-               String appExecutableName = _AppInfo::GetAppExecutableName();
-               length = (appExecutableName.GetLength() + 1) * sizeof(wchar_t);
-               if (length > 255)
-               {
-                       length = 255;
-               }
-
-               //SysTryReturnResult(NID_IO, appExecutableName.GetLength() > 0, E_SYSTEM, "App Executable name of AppId(%ls) dose not exist.", appId.GetPointer());
-               if (appExecutableName.GetLength() != 0)
-               {
-                       memcpy(helloMessage.appExecutableName, appExecutableName.GetPointer(), length);
-               }
        }
 
        client = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -206,8 +202,26 @@ _IpcClient::MakeConnection(bool forReverse)
        strncpy(server.sun_path, socketName.c_str(), socketNameLength);
        serverLen = sizeof(server);
 
-       ret = connect(client, (struct sockaddr*) &server, serverLen);
-       if (ret != 0)
+       // Retry if the server is not ready
+       retry = 5;
+       while (retry > 0)
+       {
+               ret = connect(client, (struct sockaddr*) &server, serverLen);
+               if (ret < 0 && errno == ENOENT)
+               {
+                       SysLog(NID_IO, "The server is not ready. %d", retry);
+
+                       usleep(1000 * 1000);
+
+                       --retry;
+               }
+               else
+               {
+                       break;
+               }
+       }
+
+       if (ret < 0)
        {
                SysTryCatch(NID_IO, errno == EINPROGRESS, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] Failed to connect to server(%s) : %s",
                                   socketName.c_str(), strerror(errno));
@@ -222,11 +236,9 @@ _IpcClient::MakeConnection(bool forReverse)
                FD_ZERO(&rset);
                FD_SET(client, &rset);
                wset = rset;
-               timeout.tv_sec = 10; // FIXME: replace 10 with const int
+               timeout.tv_sec = 10;
                timeout.tv_usec = 0;
 
-               // FIXME:
-               // replace select with poll
                while (true)
                {
                        ret = select(client+1, &rset, &wset, NULL, &timeout);
@@ -324,10 +336,17 @@ _IpcClient::HandleReceivedMessage(GIOChannel* source, GIOCondition condition)
 
        if (condition & G_IO_HUP)
        {
+               SysLog(NID_IO, "G_IO_HUP, the connection is closed.");
+
                g_source_destroy(__pReverseSource);
                g_source_unref(__pReverseSource);
                __pReverseSource = null;
 
+               if (__pListener)
+               {
+                       __pListener->OnIpcServerDisconnected(*this);
+               }
+
                return FALSE;
        }
        else if (condition & G_IO_IN)
@@ -341,8 +360,17 @@ _IpcClient::HandleReceivedMessage(GIOChannel* source, GIOCondition condition)
                {
                        pGError = null;
                        status = g_io_channel_read_chars(source, (char*) __messageBuffer, __MAX_MESSAGE_BUFFER_SIZE, &readSize, &pGError);
-                       if (status == G_IO_STATUS_EOF)
+                       if (status == G_IO_STATUS_EOF || status == G_IO_STATUS_ERROR)
                        {
+                               if (status == G_IO_STATUS_EOF)
+                               {
+                                       SysLog(NID_IO, "G_IO_STATUS_EOF, the connection is closed.");
+                               }
+                               else
+                               {
+                                       SysLog(NID_IO, "G_IO_STATUS_ERROR, the connection is closed. ");
+                               }
+
                                pGError = null;
 
                                g_io_channel_shutdown(source, FALSE, &pGError);
@@ -351,6 +379,11 @@ _IpcClient::HandleReceivedMessage(GIOChannel* source, GIOCondition condition)
                                g_source_unref(__pReverseSource);
                                __pReverseSource = null;
 
+                               if (__pListener)
+                               {
+                                       __pListener->OnIpcServerDisconnected(*this);
+                               }
+
                                return FALSE;
                        }
 
@@ -458,6 +491,25 @@ _IpcClient::SendAsync(IPC::Message* pMessage)
        while (remain > 0)
        {
                written = write(fd, (char*) pData, remain);
+               if (written < 0)
+               {
+                       ReleaseFd(fd);
+
+                       if (errno == EAGAIN)
+                       {
+                               SysLogException(NID_IO, E_RESOURCE_UNAVAILABLE, "[E_RESOURCE_UNAVAILABLE] The socket buffer is full.");
+                               return E_RESOURCE_UNAVAILABLE;
+                       }
+                       else if (errno == EPIPE)
+                       {
+                               SysLogException(NID_IO, E_INVALID_CONNECTION, "[E_INVALID_CONNECTION] The socket connection is closed.");
+                               return E_INVALID_CONNECTION;
+                       }
+
+                       SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to send a request: %d, %s", errno, strerror(errno));
+                       return E_SYSTEM;
+               }
+
                remain -= written;
                pData += written;
        }
@@ -484,8 +536,6 @@ _IpcClient::SendSync(IPC::Message* pMessage)
 
        std::string message;
 
-       struct pollfd pfd;
-
        IPC::Message* pReply = null;
        MessageReplyDeserializer* pReplyDeserializer = null;
        IPC::SyncMessage* pSyncMessage = dynamic_cast <IPC::SyncMessage*>(pMessage);
@@ -502,21 +552,59 @@ _IpcClient::SendSync(IPC::Message* pMessage)
        while (remain > 0)
        {
                written = write(fd, (char*) pData, remain);
+               if (written < 0)
+               {
+                       ReleaseFd(fd);
+
+                       if (errno == EAGAIN)
+                       {
+                               SysLogException(NID_IO, E_RESOURCE_UNAVAILABLE, "[E_RESOURCE_UNAVAILABLE] The socket buffer is full.");
+                               return E_RESOURCE_UNAVAILABLE;
+                       }
+                       else if (errno == EPIPE)
+                       {
+                               SysLogException(NID_IO, E_INVALID_CONNECTION, "[E_INVALID_CONNECTION] The socket connection is closed.");
+                               return E_INVALID_CONNECTION;
+                       }
+
+                       SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to send a request: %d, %s", errno, strerror(errno));
+                       return E_SYSTEM;
+               }
+
                remain -= written;
                pData += written;
        }
 
        // Wait reply
+       struct pollfd pfd;
+
        pfd.fd = fd;
        pfd.events = POLLIN | POLLRDHUP;
        pfd.revents = 0;
 
+       int ret = 0;
+
        while (true)
        {
-               poll(&pfd, 1, -1);
+               ret = poll(&pfd, 1, -1);
+               if (ret < 0)
+               {
+                       if (errno == EINTR)
+                       {
+                               continue;
+                       }
+
+                       SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] Failed to poll (%d, %s).", errno, strerror(errno));
+
+                       ReleaseFd(fd);
+                       return E_SYSTEM;
+               }
 
                if (pfd.revents & POLLRDHUP)
                {
+                       SysLogException(NID_IO, E_SYSTEM, "[E_SYSTEM] POLLRDHUP");
+
+                       ReleaseFd(fd);
                        return E_SYSTEM;
                }
 
@@ -525,13 +613,23 @@ _IpcClient::SendSync(IPC::Message* pMessage)
                        readSize = read(fd, buffer, 1024);
                }
 
-               message.append(buffer, readSize);
+               if (readSize > 0)
+               {
+                       message.append(buffer, readSize);
+               }
 
                pEndOfMessage = (char*) IPC::Message::FindNext(message.data(), message.data() + message.size());
                if (pEndOfMessage)
                {
                        pReply = new (std::nothrow) IPC::Message(message.data(), pEndOfMessage - message.data());
-                       SysTryReturnResult(NID_IO, pReply != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
+                       if (pReply == null)
+                       {
+                               SysLogException(NID_IO, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
+
+                               ReleaseFd(fd);
+                               return E_OUT_OF_MEMORY;
+                       }
+
                        break;
                }
        }