+++ /dev/null
-//
-// Open Service Platform
-// Copyright (c) 2012 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Apache License, Version 2.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-/**
- * @file FIo_ChannelCAppStub.cpp
- * @brief This is the implementation file for the _ChannelCAppStub class.
- *
- */
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <iostream>
-
-#include <unique_ptr.h>
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <errno.h>
-
-#include <sys/smack.h>
-
-#include <FBase_StringConverter.h>
-#include <FBaseDataType.h>
-#include <FBaseLong.h>
-#include <FBaseColArrayList.h>
-
-#include <FBaseRt_EventDispatcher.h>
-#include <FBaseSysLog.h>
-#include <FBaseUtilStringTokenizer.h>
-#include <FIo_ChannelServiceStub.h>
-#include <FApp_AppInfo.h>
-
-#include "FIo_ChannelCAppStub.h"
-
-#define MAX_BUFFER_LENGTH 4096
-
-static const int TOKEN_LENGTH = 7;
-static const int CAPP_PADDING_LENGTH = 7;
-
-using namespace std;
-
-using namespace Tizen::Base;
-using namespace Tizen::Base::Collection;
-using namespace Tizen::Base::Runtime;
-using namespace Tizen::Base::Utility;
-using namespace Tizen::Io;
-using namespace Tizen::App;
-
-using namespace std;
-
-namespace Tizen { namespace Io
-{
-
-_ChannelCAppStub::_ChannelCAppStub(void)
- :__pChannelService(null)
- , __pGMainContext(null)
- , __pConnectGSource(null)
-{
-}
-
-_ChannelCAppStub::~_ChannelCAppStub(void)
-{
- if (__pConnectGSource != null)
- {
- g_source_destroy(__pConnectGSource);
- g_source_unref(__pConnectGSource);
- __pConnectGSource = null;
- }
- __clients.clear();
-}
-
-_ChannelCAppStub::_ChannelInfo::_ChannelInfo(void)
- : pClientInfo(null)
- , pGIOChannel(null)
- , pGSource(null)
- , destroySource(true)
-{
-
-}
-_ChannelCAppStub::_ChannelInfo::~_ChannelInfo(void)
-{
- if (pGIOChannel != null)
- {
- g_io_channel_unref(pGIOChannel);
- }
-
- if (pGSource != null)
- {
- if (destroySource)
- {
- g_source_destroy(pGSource);
- }
-
- g_source_unref(pGSource);
- }
-}
-
-_ChannelCAppStub::_ClientInfo::_ClientInfo(void)
- : clientId(-1)
- , pChannelStub(null)
-{
-
-}
-
-_ChannelCAppStub::_ClientInfo::~_ClientInfo(void)
-{
- channels.clear();
-}
-
-result
-_ChannelCAppStub::Construct(void)
-{
- GSource* pGSource = null;
- GIOChannel* pGIOChannel = null;
- const char* pSocketName = "/tmp/osp.io.socketserver.channelmanager\0";
- size_t socketNameLength = 0;
- struct sockaddr_un serverAddress;
- int serverSocket = -1;
- socklen_t serverLen = 0;
- int ret = 0;
- result r = E_SUCCESS;
-
- socketNameLength = strlen(pSocketName) + 1;
- SysTryReturnResult(NID_IO, socketNameLength < 108, E_SYSTEM,
- "Server name is too long.");
-
- __pGMainContext = g_main_context_get_thread_default(); //get own gmain context except default thread
- if (__pGMainContext == null)
- {
- __pGMainContext = g_main_context_default(); //get gmain context from me (default)
- SysTryReturnResult(NID_IO, __pGMainContext != null, E_SYSTEM,
- "Failed to get glib context.");
- }
-
- ret = unlink(pSocketName);
- SysTryLog(NID_IO, ret == 0, "Unlinking a socket %s has failed.. but it is not a problem.", pSocketName);
-
- serverSocket = socket(AF_UNIX, SOCK_STREAM, 0);
- SysTryReturnResult(NID_IO, serverSocket != -1, E_SYSTEM,
- "Failed to create a socket.");
-
- // SMACK (Add a * label to socket)
- if(smack_fsetlabel(serverSocket, "@", SMACK_LABEL_IPOUT) != 0)
- {
- SysTryCatch(NID_IO, errno == EOPNOTSUPP, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] SMACK labeling failed");
- SysLog(NID_IO, "Kernel doesn't have Smack.");
- }
-
- if(smack_fsetlabel(serverSocket, "*", SMACK_LABEL_IPIN) != 0)
- {
- SysTryCatch(NID_IO, errno == EOPNOTSUPP, r = E_SYSTEM, E_SYSTEM, "[E_SYSTEM] SMACK labeling failed");
- SysLog(NID_IO, "Kernel doesn't have Smack.");
- }
-
- bzero(&serverAddress, sizeof(serverAddress));
- serverAddress.sun_family = AF_UNIX;
- strncpy(serverAddress.sun_path, pSocketName, socketNameLength);
- serverLen = sizeof(serverAddress);
-
- ret = bind(serverSocket, (const struct sockaddr*) &serverAddress, serverLen);
- SysTryCatch(NID_IO, ret != -1, r = E_SYSTEM, E_SYSTEM,
- "[E_SYSTEM] Failed to bind a socket(%d, %s): %s", serverSocket, pSocketName, strerror(errno));
-
- ret = chmod(pSocketName, 0666);
- SysTryCatch(NID_IO, ret == 0, r = E_SYSTEM, E_SYSTEM,
- "[E_SYSTEM] Failed to change permission of a socket(%d, %s): %s", serverSocket,
- pSocketName, strerror(errno));
-
- listen(serverSocket, 5);
-
- pGIOChannel = g_io_channel_unix_new(serverSocket);
- SysTryCatch(NID_IO, pGIOChannel != null, r = E_SYSTEM, E_SYSTEM,
- "[E_SYSTEM] Failed to create GIOChannel for socket.");
-
- // socket will be closed when pGIOChannel is deleted.
- g_io_channel_set_close_on_unref(pGIOChannel, TRUE);
- serverSocket = -1;
-
- pGSource = g_io_create_watch(pGIOChannel, (GIOCondition)(G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP));
- SysTryCatch(NID_IO, pGSource != null, r = E_SYSTEM, E_SYSTEM,
- "[E_SYSTEM] Failed to create GSource for socket.");
-
- // channel will be delete when pGSource is deleted.
- g_io_channel_unref(pGIOChannel);
- pGIOChannel = null;
-
- g_source_set_callback(pGSource, (GSourceFunc) OnConnectionRequest, this, NULL);
- g_source_attach(pGSource, __pGMainContext);
-
- __pConnectGSource = pGSource;
-
- return E_SUCCESS;
-
-CATCH:
- if (pGIOChannel != null)
- {
- g_io_channel_unref(pGIOChannel);
- }
-
- if (serverSocket != -1)
- {
- close(serverSocket);
- }
-
- if (__pGMainContext)
- {
- g_main_context_unref(__pGMainContext);
- __pGMainContext = null;
- }
-
- return r;
-}
-
-void
-_ChannelCAppStub::SetChannelService(_ChannelService& service)
-{
- __pChannelService = &service;
-}
-
-struct HelloMessage
-{
- int pid;
- char appId[256];
-};
-
-gboolean
-_ChannelCAppStub::OnConnectionRequest(GIOChannel* source, GIOCondition condition, gpointer data)
-{
- int serverFd = -1;
- int clientFd = -1;
- struct sockaddr_un clientAddress;
- socklen_t clientLen = sizeof(clientAddress);
- GSource* pGSource = null;
- GIOChannel* pGIOChannel = null;
- GError* pGError = null;
- _ClientInfo* pClientInfo = null;
- _ChannelInfo* pChannelInfo = null;
- HelloMessage helloMessage;
- int readSize = 0;
-
- _ChannelCAppStub* pChannelStub = static_cast< _ChannelCAppStub* >(data);
- SysTryReturn(NID_IO, pChannelStub != null, FALSE, E_SYSTEM,
- "[E_SYSTEM] pChannelStub is null.");
-
- serverFd = g_io_channel_unix_get_fd(source);
- clientFd = accept(serverFd, (struct sockaddr*) &clientAddress, &clientLen);
- SysTryReturn(NID_IO, clientFd != -1, E_SYSTEM, FALSE, "[E_SYSTEM] Failed to accept.");
-
-
- readSize = read(clientFd, &helloMessage, sizeof(helloMessage));
- helloMessage.appId[255] = '\0';
-
- SysLog(NID_IO, " >> Channel Service: accepted client fd: %d, client: %d, app: %s",
- clientFd, helloMessage.pid, helloMessage.appId);
-
- pGIOChannel = g_io_channel_unix_new(clientFd);
- SysTryCatch(NID_IO, pGIOChannel != null, , E_SYSTEM,
- "[E_SYSTEM] Failed to create GIOChannel.");
-
- g_io_channel_set_encoding(pGIOChannel, NULL, &pGError);
- g_io_channel_set_flags(pGIOChannel, G_IO_FLAG_NONBLOCK, &pGError);
-
- g_io_channel_set_close_on_unref(pGIOChannel, TRUE);
- clientFd = -1;
-
- pClientInfo = pChannelStub->__clients[helloMessage.pid];
- if (pClientInfo == null) // first connection request from this client
- {
- SysLog(NID_IO, "First connection!! [%s]", helloMessage.appId);
-
- pClientInfo = new (std::nothrow) _ClientInfo;
- SysTryCatch(NID_IO, pClientInfo != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
-
- pClientInfo->pChannelStub = pChannelStub;
- pClientInfo->clientId = helloMessage.pid;
- pClientInfo->appId = helloMessage.appId;
-
- pChannelStub->__clients[helloMessage.pid] = pClientInfo;
- }
-
- pChannelInfo = new (std::nothrow) _ChannelInfo;
- SysTryCatch(NID_IO, pChannelInfo != null, , E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] The memory is insufficient.");
-
- pGSource = g_io_create_watch(pGIOChannel, (GIOCondition) (G_IO_IN | G_IO_ERR | G_IO_NVAL | G_IO_HUP));
- g_source_set_callback(pGSource, (GSourceFunc) OnReadMessage, pChannelInfo, NULL);
- g_source_attach(pGSource, pChannelStub->__pGMainContext);
-
- pChannelInfo->pClientInfo = pClientInfo;
- pChannelInfo->pGIOChannel = pGIOChannel;
- pChannelInfo->pGSource = pGSource;
-
- pClientInfo->channels.push_back(pChannelInfo);
-
- // Stores client info to _ChannelService
- pChannelStub->__pChannelService->RegisterChannel(pClientInfo->appId, helloMessage.pid, pGIOChannel);
-
- return TRUE;
-
-CATCH:
- if (pGIOChannel != null)
- {
- g_io_channel_unref(pGIOChannel);
- }
-
- if (clientFd != -1)
- {
- close(clientFd);
- }
-
- return FALSE;
-}
-
-gboolean
-_ChannelCAppStub::OnReadMessage(GIOChannel* source, GIOCondition condition, gpointer data)
-{
- gboolean ret = FALSE;
-
- _ChannelInfo* pChannelInfo = (_ChannelInfo*) data;
- _ClientInfo* pClientInfo = pChannelInfo->pClientInfo;
- _ChannelCAppStub* pChannelStub = (_ChannelCAppStub*) pClientInfo->pChannelStub;
-
- ret = pChannelStub->HandleReceivedMessage(source, condition, data);
-
- return ret;
-}
-
-gboolean
-_ChannelCAppStub::HandleReceivedMessage(GIOChannel* source, GIOCondition condition, gpointer data)
-{
- GIOStatus status;
- GError* pGError = null;
- gsize readBytes = 0;
- result r = E_SUCCESS;
-
- SysLog(NID_IO, "fd: %d, condition :0x%x", g_io_channel_unix_get_fd(source), condition);
-
- _ChannelInfo* pChannelInfo = (_ChannelInfo*) data;
- _ClientInfo* pClientInfo = pChannelInfo->pClientInfo;
- _ChannelCAppStub* pChannelStub = pClientInfo->pChannelStub;
-
- if (condition & G_IO_HUP)
- {
- SysLog(NID_IO, " G_IO_HUP, the connection is closed");
- int clientId = pClientInfo->clientId;
-
- g_io_channel_shutdown(source, FALSE, &pGError);
-
- for (unsigned int i = 0; i < pClientInfo->channels.size(); i++)
- {
- if (pChannelInfo == pClientInfo->channels[i])
- {
- pClientInfo->channels.erase(pClientInfo->channels.begin() + i);
-
- pChannelInfo->destroySource = false;
- delete pChannelInfo;
-
- break;
- }
-
- }
-
- if (pClientInfo->channels.size() == 0)
- {
- SysLog(NID_IO, "All connections of client(%d) are closed. delete client info", clientId);
-
- pChannelStub->__pChannelService->UnregisterChannel(clientId);
-
- __clients[clientId] = null;
-
- delete pClientInfo;
- }
-
- return FALSE;
- }
- else if (condition & G_IO_IN)
- {
- unique_ptr<char[]> pBuffer(new char[MAX_BUFFER_LENGTH]);
- pGError = null;
- status = g_io_channel_read_chars(source, pBuffer.get(), MAX_BUFFER_LENGTH, &readBytes, &pGError);
- if (status != G_IO_STATUS_NORMAL)
- {
- 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);
-
- int clientId = pClientInfo->clientId;
-
- for (unsigned int i = 0; i < pClientInfo->channels.size(); i++)
- {
- if (pChannelInfo == pClientInfo->channels[i])
- {
- pClientInfo->channels.erase(pClientInfo->channels.begin() + i);
-
- //pChannelInfo->destroySource = false;
- pChannelInfo->destroySource = true;
- delete pChannelInfo;
- break;
- }
- }
-
- if (pClientInfo->channels.size() == 0)
- {
- SysLog(NID_IO, "All connections of client(%d) are closed. delete client info", clientId);
-
- pChannelStub->__pChannelService->UnregisterChannel(clientId);
-
- __clients[clientId] = null;
-
- delete pClientInfo;
- }
-
- return FALSE;
- }
- }
-
- SysSecureLog(NID_IO, "CAppChannel >> Channel Server: readBytes: %d, readBuf: %s", readBytes, pBuffer.get());
-
- SysTryReturn(NID_IO, readBytes != 0, FALSE, E_SYSTEM, "[E_SYSTEM] Received data is empty.");
-
- String srcAppId = pClientInfo->appId;
-
- // Parse the header
- string buffer(pBuffer.get());
- string tokenStr("::");
- RequestId reqId = 0;
- size_t pos = 0;
- size_t lastPos = 0;
-
- lastPos = buffer.find(tokenStr);
-
- // AppId
- String appId((buffer.substr(pos, lastPos-pos)).c_str());
-
- SysLog(NID_IO, "CAppChannel >> src = %ls / dest = %ls", srcAppId.GetPointer(), appId.GetPointer());
-
- pos = lastPos + tokenStr.length();
- lastPos = buffer.find(tokenStr, pos);
-
- // Request ID
- string requestId(buffer.substr(pos, lastPos-pos));
- reqId = atol(requestId.c_str());
-
- SysLog(NID_IO, "CAppChannel >> request = %d", reqId);
-
- pos = lastPos + tokenStr.length();
-
- // Parse the data
- ArrayList list;
- list.Construct();
-
- size_t bufferSize = buffer.length();
- int tokenCount = 0;
- string token;
- while (pos < bufferSize)
- {
- // Get length of each token
- token = buffer.substr(pos, TOKEN_LENGTH);
- pos += TOKEN_LENGTH;
-
- if (token == "0000000")
- {
- SysLog(NID_IO, "CAppChannel >> length = 0, token = empty string");
- list.Add(*(new String()));
- }
- else
- {
- tokenCount = atoi(token.c_str());
- token = buffer.substr(pos, tokenCount);
- pos += tokenCount;
-
- SysLog(NID_IO, "CAppChannel >> length = %d, token = %s", tokenCount, token.c_str());
- list.Add(*(new String(token.c_str())));
- }
- }
-
- r = pChannelStub->__pChannelService->SendRequest(srcAppId, appId, list, reqId);
- SysTryReturn(NID_IO, !IsFailed(r), FALSE, E_SYSTEM, "[E_SYSTEM] Failed to send request.");
-
- list.RemoveAll(true);
- }
- else
- {
- SysLog(NID_IO, " >> Channel Service: else !!!");
- }
-
- return TRUE;
-}
-
-bool
-_ChannelCAppStub::SendResponse(int requestId, void* pGIOChannel, const ArrayList& args)
-{
- gsize writtenBytes = 0;
- GError* pGError = null;
-
- // Parse the data
- String str;
- String item;
- String lengthString;
- int count = args.GetCount();
- int itemLength = 0;
- int paddingLength = 0;
- result r = E_SUCCESS;
- SysLog(NID_IO, "item count: %d", count);
-
- for (int i = 0; i < count; ++i)
- {
- item = *((String*)args.GetAt(i));
- unique_ptr<char[]> pItemStr(_StringConverter::CopyToCharArrayN(item));
- itemLength = strlen(pItemStr.get());
- lengthString = Integer::ToString(itemLength);
- r = item.Insert(lengthString, 0);
- SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM, "[E_SYSTEM] Failed to compose the response message.");
-
- // padding 7 digit
- paddingLength = CAPP_PADDING_LENGTH - lengthString.GetLength();
- for (int j = 0; j < paddingLength; j++)
- {
- r = item.Insert(L'0', 0);
- SysTryReturn(NID_IO, !IsFailed(r), false, E_SYSTEM, "[E_SYSTEM] Failed to compose the response message.");
- }
-
- str.Append(item);
- }
-
- SysSecureLog(NID_IO, "data: %ls, length: %d", str.GetPointer(), str.GetLength());
-
- // Add a RequestId
- str.Append(L"|||");
- str.Append(requestId);
- str.Append(L"|");
-
- // Send a data
- unique_ptr<char[]> pStr(_StringConverter::CopyToCharArrayN(str));
-
- itemLength = strlen(pStr.get());
-
- g_io_channel_write_chars((GIOChannel*)pGIOChannel, (char*)pStr.get(), itemLength, &writtenBytes, &pGError);
- g_io_channel_flush((GIOChannel*)pGIOChannel, &pGError);
-
- return true;
-}
-
-}}
-
#include "FIo_ChannelService.h"
#include "FIo_ChannelMessages.h"
#include "FIo_IChannelServiceStub.h"
-#include "FIo_ChannelCAppStub.h"
-using namespace std;
using namespace Tizen::Base;
using namespace Tizen::Base::Collection;
using namespace Tizen::Base::Runtime;
{
static _StringHashProvider hashProvider;
static _StringComparer stringComparer;
- result r = E_SUCCESS;
__channels.Construct(0, 0, hashProvider, stringComparer);
__pIChannelServiceStub->SetChannelService(*this);
- // Create a CAppStub
- unique_ptr<_ChannelCAppStub> pCStub(new (std::nothrow) _ChannelCAppStub());
- SysTryReturnResult(NID_IO, pCStub != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
-
- r = pCStub->Construct();
- SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Failed to create a CAppStub.");
-
- pCStub->SetChannelService(*this);
-
- pCStub.release();
-
return E_SUCCESS;
}
}
result
-_ChannelService::RegisterChannel(const String& channelId, int clientId, unsigned int type)
+_ChannelService::RegisterChannel(const String& channelId, int clientId)
{
result r = E_SUCCESS;
_ChannelInfo* pChannelInfo = null;
pChannelInfo->channelId = channelId;
pChannelInfo->clientId = clientId;
- pChannelInfo->type = type;
pChannelInfo->pGIOChannel = null;
__channels.Add(channelId, pChannelInfo);
}
result
-_ChannelService::RegisterChannel(const String& channelId, int clientId, void* pGIOChannel)
-{
- result r = E_SUCCESS;
- _ChannelInfo* pChannelInfo = null;
-
- SysLog(NID_IO, "Register a channel : [%ls]", channelId.GetPointer());
-
- r = __channels.GetValue(channelId, pChannelInfo);
- if (pChannelInfo != null)
- {
- SysTryReturnResult(NID_IO, pChannelInfo->clientId != clientId, E_SYSTEM, "Channel has already been registered.");
-
- SysLog(NID_IO, "Remove garbage values : %ls", channelId.GetPointer());
- __channels.Remove(channelId);
- }
-
- pChannelInfo = new (std::nothrow) _ChannelInfo;
- SysTryReturnResult(NID_IO, pChannelInfo != null, E_OUT_OF_MEMORY, "The memory is insufficient.");
-
- pChannelInfo->channelId = channelId;
- pChannelInfo->clientId = clientId;
- pChannelInfo->type = CAPP_CHANNEL;
- pChannelInfo->pGIOChannel = pGIOChannel;
-
- __channels.Add(channelId, pChannelInfo);
-
- return E_SUCCESS;
-}
-
-result
_ChannelService::UnregisterChannel(const String& channelId)
{
return E_SUCCESS;
SysTryReturnResult(NID_IO, pChannelInfo != null, E_OBJ_NOT_FOUND,
"Destination channel not found.");
- // Channel for CApp
- if (pChannelInfo->type == CAPP_CHANNEL)
- {
- bool ret = _ChannelCAppStub::SendResponse(requestId, pChannelInfo->pGIOChannel, args);
- SysTryReturnResult(NID_IO, ret, E_SYSTEM, "Failed to send the data to a CApp.");
- }
- // Channel for OspApp
- else
- {
- result r = __pIChannelServiceStub->SendResponse(pChannelInfo->clientId, src, dest, args, requestId);
- SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Failed to send the response data");
- }
+ result r = __pIChannelServiceStub->SendResponse(pChannelInfo->clientId, src, dest, args, requestId);
+ SysTryReturnResult(NID_IO, r == E_SUCCESS, E_SYSTEM, "Failed to send the response data");
return E_SUCCESS;
}