)
SET(SERVER_SOURCES
- ${SERVER_PATH}/main/generic-socket-manager.cpp
${SERVER_PATH}/main/socket-manager.cpp
${SERVER_PATH}/main/server-main.cpp
${SERVER_PATH}/main/service-thread.cpp
+++ /dev/null
-/*
- * Copyright (c) 2013-2020 Samsung Electronics Co., Ltd. All rights reserved.
- *
- * This file is licensed under the terms of MIT License or the Apache License
- * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
- * See the LICENSE file or the notice below for Apache License Version 2.0
- * details.
- *
- * 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 generic-socket-manager.cpp
- * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
- * @version 1.0
- * @brief Implementation of GenericSocketService and GenericSocketManager.
- */
-
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <generic-socket-manager.h>
-
-namespace SecurityManager {
-
-class SendMsgData::Internal {
-public:
- Internal(int resultCode, int fileDesc)
- : m_resultCode(resultCode)
- , m_fileDesc(fileDesc)
- {
- memset(&m_hdr, 0, sizeof(msghdr));
- memset(m_cmsgbuf, 0, CMSG_SPACE(sizeof(int)));
-
- m_iov.iov_base = &m_resultCode;
- m_iov.iov_len = sizeof(m_resultCode);
-
- m_hdr.msg_iov = &m_iov;
- m_hdr.msg_iovlen = 1;
-
- if (fileDesc != -1) {
- m_hdr.msg_control = m_cmsgbuf;
- m_hdr.msg_controllen = CMSG_SPACE(sizeof(int));
-
- cmsghdr *m_cmsg = CMSG_FIRSTHDR(&m_hdr);
- m_cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- m_cmsg->cmsg_level = SOL_SOCKET;
- m_cmsg->cmsg_type = SCM_RIGHTS;
-
- memmove(CMSG_DATA(m_cmsg), &m_fileDesc, sizeof(int));
- }
- }
-
- msghdr* data() { return &m_hdr; }
-
-private:
- msghdr m_hdr;
- iovec m_iov;
- unsigned char m_cmsgbuf[CMSG_SPACE(sizeof(int))];
- int m_resultCode;
- int m_fileDesc;
-};
-
-SendMsgData::SendMsgData()
- : m_resultCode(0)
- , m_fileDesc(-1)
- , m_flags(0)
- , m_pimpl(NULL)
-{}
-
-SendMsgData::SendMsgData(int resultCode, int fileDesc, int flags)
- : m_resultCode(resultCode)
- , m_fileDesc(fileDesc)
- , m_flags(flags)
- , m_pimpl(NULL)
-{}
-
-SendMsgData::SendMsgData(const SendMsgData &second)
- : m_resultCode(second.m_resultCode)
- , m_fileDesc(second.m_fileDesc)
- , m_flags(second.m_flags)
- , m_pimpl(NULL)
-{}
-
-SendMsgData::~SendMsgData() {
- delete m_pimpl;
-}
-
-SendMsgData& SendMsgData::operator=(const SendMsgData &second) {
- m_resultCode = second.m_resultCode;
- m_fileDesc = second.m_fileDesc;
- m_flags = second.m_flags;
- delete m_pimpl;
- m_pimpl = NULL;
- return *this;
-}
-
-msghdr* SendMsgData::getMsghdr() {
- if (!m_pimpl)
- m_pimpl = new Internal(m_resultCode, m_fileDesc);
- return m_pimpl->data();
-}
-
-int SendMsgData::flags() {
- return m_flags;
-}
-
-} // namespace SecurityManager
-
#include <credentials.h>
#include <generic-event.h>
-extern "C" {
-struct msghdr;
-} // extern "C"
-
namespace SecurityManager {
typedef int InterfaceID;
ServiceDescription(const char *path,
const char *smackLabel,
InterfaceID interfaceID = 0,
- bool useSendMsg = false,
bool systemdOnly = false)
: smackLabel(smackLabel)
, interfaceID(interfaceID)
, serviceHandlerPath(path)
- , useSendMsg(useSendMsg)
, systemdOnly(systemdOnly)
{}
SmackLabel smackLabel; // Smack label for socket
InterfaceID interfaceID; // All data from serviceHandlerPath will be marked with this interfaceHandler
ServiceHandlerPath serviceHandlerPath; // Path to file
- bool useSendMsg;
bool systemdOnly;
};
GenericSocketManager *m_serviceManager;
};
-class SendMsgData {
-public:
- class Internal;
-
- SendMsgData();
- SendMsgData(int resultCode, int fileDesc, int flags = 0);
- SendMsgData(const SendMsgData &second);
- SendMsgData& operator=(const SendMsgData &second);
- virtual ~SendMsgData();
-
- msghdr* getMsghdr();
- int flags();
-private:
- int m_resultCode;
- int m_fileDesc;
- int m_flags;
- Internal *m_pimpl;
-};
-
struct GenericSocketManager {
virtual void MainLoop() = 0;
virtual void RegisterSocketService(GenericSocketService *ptr) = 0;
virtual void Close(ConnectionID connectionID) = 0;
virtual void Write(ConnectionID connectionID, const RawBuffer &rawBuffer) = 0;
- virtual void Write(ConnectionID connectionID, const SendMsgData &sendMsgData) = 0;
virtual ~GenericSocketManager(){}
};
virtual void RegisterSocketService(GenericSocketService *service);
virtual void Close(ConnectionID connectionID);
virtual void Write(ConnectionID connectionID, const RawBuffer &rawBuffer);
- virtual void Write(ConnectionID connectionID, const SendMsgData &sendMsgData);
protected:
void CreateDomainSocket(
void ReadyForRead(int sock);
void ReadyForWrite(int sock);
- void ReadyForWriteBuffer(int sock);
- void ReadyForSendMsg(int sock);
void ReadyForAccept(int sock);
void ProcessQueue(void);
void NotifyMe(void);
bool isListen;
bool isOpen;
bool isTimeout;
- bool useSendMsg;
InterfaceID interfaceID;
GenericSocketService *service;
time_t timeout;
RawBuffer rawBuffer;
- std::queue<SendMsgData> sendMsgDataQueue;
int counter;
SocketDescription()
: isListen(false)
, isOpen(false)
, isTimeout(false)
- , useSendMsg(false)
, interfaceID(-1)
, service(NULL)
, timeout(0)
RawBuffer rawBuffer;
};
- struct WriteData {
- ConnectionID connectionID;
- SendMsgData sendMsgData;
- };
-
struct Timeout {
time_t time;
int sock;
bool m_working;
std::mutex m_eventQueueMutex;
std::queue<WriteBuffer> m_writeBufferQueue;
- std::queue<WriteData> m_writeDataQueue;
std::queue<ConnectionID> m_closeQueue;
int m_notifyMe[2];
int m_counter;
auto &desc = CreateDefaultReadSocketDescription(client, true);
desc.interfaceID = m_socketDescriptionVector[sock].interfaceID;
desc.service = m_socketDescriptionVector[sock].service;
- desc.useSendMsg = m_socketDescriptionVector[sock].useSendMsg;
GenericSocketService::AcceptEvent event(
ConnectionID{client, desc.counter},
}
}
-void SocketManager::ReadyForSendMsg(int sock) {
- auto &desc = m_socketDescriptionVector[sock];
-
- if (desc.sendMsgDataQueue.empty()) {
- FD_CLR(sock, &m_writeSet);
- return;
- }
-
- auto data = desc.sendMsgDataQueue.front();
- ssize_t result = sendmsg(sock, data.getMsghdr(), data.flags());
-
- if (result == -1) {
- int err = errno;
- switch (err) {
- case EAGAIN:
- case EINTR:
- break;
- case EPIPE:
- default:
- LogError("Error during send: " << GetErrnoString(err));
- CloseSocket(sock);
- break;
- }
- return;
- } else {
- desc.sendMsgDataQueue.pop();
- }
-
- if (desc.sendMsgDataQueue.empty()) {
- FD_CLR(sock, &m_writeSet);
- }
-
- desc.timeout = monotonicNow() + SOCKET_TIMEOUT;
-
- GenericSocketService::WriteEvent event;
- event.connectionID.sock = sock;
- event.connectionID.counter = desc.counter;
- event.size = result;
- event.left = desc.sendMsgDataQueue.size();
-
- desc.service->Event(std::move(event));
-}
-
-void SocketManager::ReadyForWriteBuffer(int sock) {
+void SocketManager::ReadyForWrite(int sock) {
auto &desc = m_socketDescriptionVector[sock];
size_t size = desc.rawBuffer.size();
ssize_t result = write(sock, &desc.rawBuffer[0], size);
desc.service->Event(std::move(event));
}
-void SocketManager::ReadyForWrite(int sock) {
- m_socketDescriptionVector[sock].useSendMsg ?
- ReadyForSendMsg(sock) : ReadyForWriteBuffer(sock);
-}
-
void SocketManager::MainLoop() {
// remove evironment values passed by systemd
sd_listen_fds(1);
description.isListen = true;
description.interfaceID = desc.interfaceID;
- description.useSendMsg = desc.useSendMsg;
description.service = service;
LogDebug("Listen on socket: " << sockfd <<
NotifyMe();
}
-void SocketManager::Write(ConnectionID connectionID, const SendMsgData &sendMsgData) {
- WriteData data;
- data.connectionID = connectionID;
- data.sendMsgData = sendMsgData;
- {
- std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
- m_writeDataQueue.push(data);
- }
- NotifyMe();
-}
-
void SocketManager::NotifyMe() {
TEMP_FAILURE_RETRY(write(m_notifyMe[1], "You have message ;-)", 1));
}
void SocketManager::ProcessQueue() {
WriteBuffer buffer;
- WriteData data;
{
std::lock_guard<std::mutex> ulock(m_eventQueueMutex);
while (!m_writeBufferQueue.empty()) {
continue;
}
- if (desc.useSendMsg) {
- LogError("Some service tried to push rawdata to socket that usees sendmsg! Socket: "
- << buffer.connectionID.sock);
- continue;
- }
-
std::copy(
buffer.rawBuffer.begin(),
buffer.rawBuffer.end(),
FD_SET(buffer.connectionID.sock, &m_writeSet);
}
-
- while (!m_writeDataQueue.empty()) {
- data = m_writeDataQueue.front();
- m_writeDataQueue.pop();
-
- auto &desc = m_socketDescriptionVector[data.connectionID.sock];
-
- if (!desc.isOpen) {
- LogDebug("Received packet for sendmsg but connection is closed. Packet ignored! Socket: "
- << data.connectionID.sock);
- continue;
- }
-
- if (desc.counter != data.connectionID.counter)
- {
- LogDebug("Received packet for write but counter is broken. Packet ignored! Socket: "
- << data.connectionID.sock);
- continue;
- }
-
- if (!desc.useSendMsg) {
- LogError("Some service tries to push SendMsgData to socket that uses write! Socket: "
- << data.connectionID.sock);
- continue;
- }
-
- desc.sendMsgDataQueue.push(data.sendMsgData);
-
- FD_SET(data.connectionID.sock, &m_writeSet);
- }
}
while (1) {
desc.service = NULL;
desc.interfaceID = -1;
desc.rawBuffer.clear();
- while (!desc.sendMsgDataQueue.empty())
- desc.sendMsgDataQueue.pop();
if (service)
service->Event(std::move(event));
{SERVICE_SOCKET, /* path */
"*", /* smackLabel label (not used, we rely on systemd) */
IFACE, /* InterfaceID */
- false, /* useSendMsg */
false}, /* systemdOnly */
};
}