From 112f8cce4dcabd4be3b6fcf836fc875830e441f3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Oskar=20=C5=9Awitalski?= Date: Tue, 7 Jun 2016 07:35:29 +0200 Subject: [PATCH] Add socket methods MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Change-Id: I91b3566ec0abe2034e3a9dac29271ca5280f507a Signed-off-by: Oskar Świtalski --- src/common/CMakeLists.txt | 2 + src/common/socket/SelectRead.cpp | 64 +++++++++++++++ src/common/socket/SelectRead.h | 49 ++++++++++++ src/common/socket/Socket.cpp | 163 +++++++++++++++++++++++++++++++++++++++ src/common/socket/Socket.h | 40 ++++++++++ 5 files changed, 318 insertions(+) create mode 100644 src/common/socket/SelectRead.cpp create mode 100644 src/common/socket/SelectRead.h create mode 100644 src/common/socket/Socket.cpp create mode 100644 src/common/socket/Socket.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index da7fe96..8d1e37e 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -37,6 +37,8 @@ INCLUDE_DIRECTORIES( SET(COMMON_SOURCES ${COMMON_PATH}/log/alog.cpp + ${COMMON_PATH}/socket/Socket.cpp + ${COMMON_PATH}/socket/SelectRead.cpp ${COMMON_PATH}/translator/Translator.cpp ${COMMON_PATH}/types/AgentErrorMsg.cpp ${COMMON_PATH}/util/SafeFunction.cpp diff --git a/src/common/socket/SelectRead.cpp b/src/common/socket/SelectRead.cpp new file mode 100644 index 0000000..aaf1343 --- /dev/null +++ b/src/common/socket/SelectRead.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co. + * + * 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 SelectRead.cpp + * @author Oskar Świtalski + * @brief Definition of SelectRead class + */ + +#include "SelectRead.h" + +#include + +namespace AskUser { + +namespace Socket { + +SelectRead::SelectRead() : m_exec(true), m_timeout({0, 0}) {} + +void SelectRead::add(int fd) { + if (m_exec) { + FD_ZERO(&m_set); + m_exec = false; + } + + FD_SET(fd, &m_set); + m_nfds = m_nfds > fd ? m_nfds : fd; +} + +int SelectRead::exec() { + int result = 0; + + m_exec = true; + + result = select(m_nfds + 1, &m_set, nullptr, nullptr, &m_timeout); + if (result == -1) + throw ErrnoException("Select failed"); + + return result; +} + +bool SelectRead::isSet(int fd) { + return FD_ISSET(fd, &m_set); +} + +void SelectRead::setTimeout(int ms) { + m_timeout.tv_usec = ms * 1000; +} + +} /* namespace Socket */ + +} /* namespace AskUser */ diff --git a/src/common/socket/SelectRead.h b/src/common/socket/SelectRead.h new file mode 100644 index 0000000..3646ef5 --- /dev/null +++ b/src/common/socket/SelectRead.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co. + * + * 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 SelectRead.h + * @author Oskar Świtalski + * @brief Declaration of SelectRead class + */ + +#pragma once + +#include + +namespace AskUser { + +namespace Socket { + +class SelectRead { +public: + SelectRead(); + + void add(int fd); + int exec(); + bool isSet(int fd); + void setTimeout(int ms); +private: + bool m_exec; + + fd_set m_set; + int m_nfds; + + timeval m_timeout; +}; + +} /* namespace Socket */ + +} /* namespace AskUser */ diff --git a/src/common/socket/Socket.cpp b/src/common/socket/Socket.cpp new file mode 100644 index 0000000..e9186b0 --- /dev/null +++ b/src/common/socket/Socket.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co. + * + * 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 Socket.cpp + * @author Oskar Świtalski + * @brief Implementation of Socket methods + */ + +#include "Socket.h" + +#include +#include + +#include +#include +#include +#include + +namespace AskUser { + +namespace Socket { + +int accept(int fd) { + int retFd = TEMP_FAILURE_RETRY(::accept(fd, nullptr, nullptr)); + if (retFd < 0) + throw ErrnoException("Accept socket error"); + + ALOGD("Accepted socket <" << retFd << ">"); + + return retFd; +} + +void close(int fd) { + int result = TEMP_FAILURE_RETRY(::close(fd)); + if (result < 0) { + ALOGE("Close socket <" << fd << "> failed"); + return; + } + + ALOGD("Closed socket <" << fd << ">"); +} + +int connect(const std::string &path) { + int fd = -1; + int result = 0; + size_t length = 0; + + sockaddr_un remote; + remote.sun_family = AF_UNIX; + + if (path.size() >= sizeof(remote.sun_path)) + throw std::invalid_argument("Path length is too big"); + strcpy(remote.sun_path, path.c_str()); + + length = strlen(remote.sun_path) + sizeof(remote.sun_family); + + fd = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + throw ErrnoException("Socket creation failed"); + + result = TEMP_FAILURE_RETRY(::connect(fd, (struct sockaddr *)&remote, length)); + if (result == -1) + throw ErrnoException("Connecting to <" + path + "> socket failed"); + + ALOGD("Connected to <" << path << "> socket"); + + return fd; +} + +int listen(const std::string &path) { + int fd = -1; + int result = 0; + size_t length = 0; + + sockaddr_un local; + local.sun_family = AF_UNIX; + + if (path.size() >= sizeof(local.sun_path)) + throw std::invalid_argument("Socket path too long"); + strcpy(local.sun_path, path.c_str()); + + length = strlen(local.sun_path) + sizeof(local.sun_family); + + result = unlink(path.c_str()); + if (result == -1 && errno != ENOENT) + throw ErrnoException("Unlink " + path + " failed"); + + fd = ::socket(AF_UNIX, SOCK_STREAM, 0); + if (fd == -1) + throw ErrnoException("Socket creation failed"); + + result = ::bind(fd, (struct sockaddr *)&local, length); + if (result == -1) + throw ErrnoException("Binding to <" + path + "> failed"); + + result = ::listen(fd, 10); + if (result == -1) + throw ErrnoException("Listen on socked failed"); + + ALOGD("Listening on <" << path << "> socket"); + + return fd; +} + +bool recv(int fd, void *buf, size_t size, int flags) { + int result = 0; + size_t bytesRead = 0; + + while (bytesRead < size) { + result = TEMP_FAILURE_RETRY(::recv(fd, buf, size, flags)); + + if (result < 0 && errno != ECONNRESET) + throw ErrnoException("Error receiving data from socket"); + else if (result <= 0) + return false; + + bytesRead += result; + + ALOGD("Recieved " << bytesRead << "/" << size << " byte(s)"); + } + + return true; +} + +bool send(int fd, const void *buf, size_t size, int flags) { + int result = 0; + size_t bytesSend = 0; + + while (bytesSend < size) { + + result = TEMP_FAILURE_RETRY(::send(fd, buf, size, flags | MSG_NOSIGNAL)); + + if (result < 0) { + if (errno == EPIPE) + return false; + else + throw ErrnoException("Error sending data to socket"); + } + + bytesSend += result; + + ALOGD("Send " << result << "/" << size << " byte(s)"); + } + + return true; +} + +} /* namespace Socket */ + +} /* namespace AskUser */ diff --git a/src/common/socket/Socket.h b/src/common/socket/Socket.h new file mode 100644 index 0000000..0f66d0d --- /dev/null +++ b/src/common/socket/Socket.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co. + * + * 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 Socket.cpp + * @author Oskar Świtalski + * @brief Declaration of Socket methods + */ + +#pragma once + +#include +#include + +namespace AskUser { + +namespace Socket { + +int accept(int fd); +void close(int fd); +int connect(const std::string &path); +int listen(const std::string &path); +bool recv(int fd, void *buf, size_t size, int flags = 0); +bool send(int fd, const void *buf, size_t size, int flags = 0); + +} /* namespace Socket */ + +} /* namespace AskUser */ -- 2.7.4