SET(LIB_CYNARA_SOURCES
${CYNARA_LIB_CYNARA_PATH}/api/client-api.cpp
${CYNARA_LIB_CYNARA_PATH}/logic/Logic.cpp
+ ${CYNARA_LIB_CYNARA_PATH}/sockets/Socket.cpp
)
INCLUDE_DIRECTORIES(
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.0
+ * @brief This file contains implementation of UNIX client socket class
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <exceptions/InitException.h>
+#include <exceptions/ServerConnectionErrorException.h>
+#include <exceptions/UnexpectedErrorException.h>
+#include <log/log.h>
+
+#include "Socket.h"
+
+namespace Cynara {
+
+Socket::Socket(const std::string &socketPath, int timeoutMiliseconds) : m_sock(-1),
+ m_socketPath(socketPath), m_pollTimeout(timeoutMiliseconds) {
+}
+
+Socket::~Socket() {
+ close();
+}
+
+void Socket::close(void) noexcept {
+ if (m_sock > -1)
+ ::close(m_sock);
+ m_sock = -1;
+}
+
+bool Socket::waitForSocket(int event) {
+ int ret;
+ pollfd desc[1];
+ desc[0].fd = m_sock;
+ desc[0].events = event;
+
+ ret = TEMP_FAILURE_RETRY(poll(desc, 1, m_pollTimeout));
+
+ if (ret == -1) {
+ int err = errno;
+ LOGE("'poll' function error [%d] : <%s>", err, strerror(err));
+ close();
+ throw UnexpectedErrorException(err, strerror(err));
+ } else if (ret == 0) {
+ LOGD("Poll timeout");
+ }
+
+ return (ret == 1);
+}
+
+int Socket::getSocketError(void) {
+ int err = 0;
+ socklen_t len = sizeof(err);
+ int ret = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &err, &len);
+ if (ret < 0) {
+ int err = errno;
+ close();
+ LOGE("'getsockopt' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+ return err;
+}
+
+bool Socket::isConnected(void) {
+ if (m_sock < 0)
+ return false;
+
+ if (getSocketError() != 0) {
+ close();
+ return false;
+ }
+
+ return true;
+}
+
+bool Socket::connect(void) {
+ sockaddr_un clientAddr;
+ int flags;
+
+ if (isConnected())
+ return true;
+
+ close();
+
+ m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (m_sock < 0) {
+ int err = errno;
+ LOGE("'socket' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+
+ if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 ||
+ fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0)
+ {
+ int err = errno;
+ close();
+ LOGE("'fcntl' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+
+ memset(&clientAddr, 0, sizeof(clientAddr));
+
+ clientAddr.sun_family = AF_UNIX;
+
+ if (m_socketPath.length() >= sizeof(clientAddr.sun_path)) {
+ close();
+ LOGE("Error: socket path <%s> is too long [%zu]. Max len is [%u]", m_socketPath.c_str(),
+ m_socketPath.length(), sizeof(clientAddr.sun_path));
+ throw InitException();
+ }
+
+ strcpy(clientAddr.sun_path, m_socketPath.c_str());
+
+ LOGD("ClientAddr.sun_path <%s>", clientAddr.sun_path);
+
+ int retval = TEMP_FAILURE_RETRY(::connect(m_sock, (struct sockaddr*)&clientAddr,
+ SUN_LEN(&clientAddr)));
+ int err = 0;
+ if (retval == -1) {
+ err = errno;
+ if (err == EINPROGRESS) {
+ if (!waitForSocket(POLLOUT)) {
+ return false;
+ }
+ err = getSocketError();
+ }
+ if (err == ECONNREFUSED) {
+ //no one is listening
+ return false;
+ }
+ close();
+ LOGE("'connect' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+
+ return isConnected();
+}
+
+bool Socket::sendToServer(BinaryQueue &queue) {
+ ssize_t done = 0;
+ bool retry = false;
+
+ RawBuffer buffer(queue.size());
+ queue.flattenConsume(buffer.data(), queue.size());
+
+ do {
+ if (!connect()) {
+ LOGE("Error connecting to socket");
+ throw ServerConnectionErrorException();
+ }
+
+ retry = false;
+ done = 0;
+ while ((buffer.size() - done) > 0) {
+ if (! waitForSocket(POLLOUT)) {
+ LOGE("Error in poll(POLLOUT)");
+ throw ServerConnectionErrorException();
+ }
+ ssize_t t = TEMP_FAILURE_RETRY(write(m_sock, buffer.data() + done,
+ buffer.size() - done));
+ if (t == -1) {
+ int err = errno;
+ if (err == EPIPE) {
+ close();
+ LOGN("Connection closed by server. Retrying to connect.");
+ retry = true;
+ break;
+ }
+ close();
+ LOGE("'write' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+ done += t;
+ }
+ } while (retry);
+
+ return true;
+}
+
+bool Socket::receiveFromServer(BinaryQueue &queue)
+{
+ if (!waitForSocket(POLLIN)) {
+ LOGE("Error in poll(POLLIN)");
+ throw ServerConnectionErrorException();
+ }
+
+ RawBuffer readBuffer(BUFSIZ);
+ ssize_t size = TEMP_FAILURE_RETRY(read(m_sock, readBuffer.data(), BUFSIZ));
+
+ if (size == -1) {
+ int err = errno;
+ LOGE("'read' function error [%d] : <%s>", err, strerror(err));
+ throw UnexpectedErrorException(err, strerror(err));
+ }
+
+ if (size == 0) {
+ LOGW("read return 0 / Connection closed by server.");
+ return false;
+ }
+ queue.appendCopy(readBuffer.data(), size);
+
+ return true;
+}
+
+} // namespace Cynara
--- /dev/null
+/*
+ * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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.h
+ * @author Bartlomiej Grzelewski <b.grzelewski@samsung.com>
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.0
+ * @brief This file contains definition of UNIX client socket class
+ */
+
+#ifndef SRC_CLIENT_SOCKETS_SOCKET_H_
+#define SRC_CLIENT_SOCKETS_SOCKET_H_
+
+#include <string>
+
+#include <common.h>
+
+namespace Cynara {
+
+class Socket {
+private:
+ int m_sock;
+
+ std::string m_socketPath;
+ int m_pollTimeout;
+
+ void close(void) noexcept;
+
+ //returns true if socket is ready
+ //returns false in case of timeout
+ //throws in critical situations
+ bool waitForSocket(int event);
+
+ //returns int errorcode read from socket
+ //throws in critical situations
+ int getSocketError(void);
+
+public:
+ Socket(const std::string &socketPath, int timeoutMiliseconds = -1);
+ ~Socket();
+
+ //returns bool connection state (true - connected, false - not connected))
+ //throws in critical situations
+ bool isConnected(void);
+
+ //returns true if connection succeeded
+ //returns false if connection was timeout or no one is listening
+ //throws in critical situations
+ bool connect(void);
+
+ //returns true if data was successfully send to server
+ //returns false if connection was lost
+ //throws ServerConnectionErrorException if cannot connect server (or timeout)
+ //throws other exceptions in critical situations
+ bool sendToServer(BinaryQueue &queue);
+
+ //returns true if data was successfully read from server
+ //returns false if connection was lost
+ //throws ServerConnectionErrorException if cannot connect server (or timeout)
+ //throws other exceptions in critical situations
+ bool receiveFromServer(BinaryQueue &queue);
+};
+
+} // namespace Cynara
+
+#endif /* SRC_CLIENT_SOCKETS_SOCKET_H_ */
+++ /dev/null
-/*
- * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact: Bumjin Im <bj.im@samsung.com>
- *
- * 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 client-common.cpp
- * @author Bartlomiej Grzelewski (b.grzelewski@samsung.com)
- * @version 1.0
- * @brief This file is implementation of client-common functions.
- */
-
-#include <fcntl.h>
-#include <poll.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include <dpl/log/log.h>
-#include <dpl/serialization.h>
-#include <dpl/singleton.h>
-#include <dpl/singleton_safe_impl.h>
-
-#include <message-buffer.h>
-
-#include <security-server.h>
-
-IMPLEMENT_SAFE_SINGLETON(SecurityServer::Log::LogSystem);
-
-namespace {
-
-const int POLL_TIMEOUT = 2000;
-
-void securityClientEnableLogSystem(void) {
- SecurityServer::Singleton<SecurityServer::Log::LogSystem>::Instance().SetTag("SECURITY_SERVER_CLIENT");
-}
-
-int waitForSocket(int sock, int event, int timeout) {
- int retval;
- pollfd desc[1];
- desc[0].fd = sock;
- desc[0].events = event;
-
- while((-1 == (retval = poll(desc, 1, timeout))) && (errno == EINTR)) {
- timeout >>= 1;
- errno = 0;
- }
-
- if (0 == retval) {
- LogDebug("Poll timeout");
- } else if (-1 == retval) {
- int err = errno;
- LogError("Error in poll: " << strerror(err));
- }
- return retval;
-}
-
-class SockRAII {
-public:
- SockRAII()
- : m_sock(-1)
- {}
-
- virtual ~SockRAII() {
- if (m_sock > -1)
- close(m_sock);
- }
-
- int Connect(char const * const interface) {
- sockaddr_un clientAddr;
- int flags;
-
- if (m_sock != -1) // guard
- close(m_sock);
-
- m_sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (m_sock < 0) {
- int err = errno;
- LogError("Error creating socket: " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- if ((flags = fcntl(m_sock, F_GETFL, 0)) < 0 ||
- fcntl(m_sock, F_SETFL, flags | O_NONBLOCK) < 0)
- {
- int err = errno;
- LogError("Error in fcntl: " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- memset(&clientAddr, 0, sizeof(clientAddr));
-
- clientAddr.sun_family = AF_UNIX;
-
- if (strlen(interface) >= sizeof(clientAddr.sun_path)) {
- LogError("Error: interface name " << interface << "is too long. Max len is:" << sizeof(clientAddr.sun_path));
- return SECURITY_SERVER_API_ERROR_NO_SUCH_SERVICE;
- }
-
- strcpy(clientAddr.sun_path, interface);
-
- LogDebug("ClientAddr.sun_path = " << interface);
-
- int retval = TEMP_FAILURE_RETRY(connect(m_sock, (struct sockaddr*)&clientAddr, SUN_LEN(&clientAddr)));
- if ((retval == -1) && (errno == EINPROGRESS)) {
- if (0 >= waitForSocket(m_sock, POLLIN, POLL_TIMEOUT)) {
- LogError("Error in waitForSocket.");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
- int error = 0;
- socklen_t len = sizeof(error);
- retval = getsockopt(m_sock, SOL_SOCKET, SO_ERROR, &error, &len);
-
- if (-1 == retval) {
- int err = errno;
- LogError("Error in getsockopt: " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- if (error == EACCES) {
- LogError("Access denied");
- return SECURITY_SERVER_API_ERROR_ACCESS_DENIED;
- }
-
- if (error != 0) {
- LogError("Error in connect: " << strerror(error));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- return SECURITY_SERVER_API_SUCCESS;
- }
-
- if (-1 == retval) {
- int err = errno;
- LogError("Error connecting socket: " << strerror(err));
- if (err == EACCES)
- return SECURITY_SERVER_API_ERROR_ACCESS_DENIED;
- if (err == ENOTSOCK)
- return SECURITY_SERVER_API_ERROR_NO_SUCH_SERVICE;
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- return SECURITY_SERVER_API_SUCCESS;
- }
-
- int Get() {
- return m_sock;
- }
-
-private:
- int m_sock;
-};
-
-} // namespace anonymous
-
-namespace SecurityServer {
-
-
-int sendToServer(char const * const interface, const RawBuffer &send, MessageBuffer &recv) {
- int ret;
- SockRAII sock;
- ssize_t done = 0;
- char buffer[2048];
-
- if (SECURITY_SERVER_API_SUCCESS != (ret = sock.Connect(interface))) {
- LogError("Error in SockRAII");
- return ret;
- }
-
- while ((send.size() - done) > 0) {
- if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
- LogError("Error in poll(POLLOUT)");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
- ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
- if (-1 == temp) {
- int err = errno;
- LogError("Error in write: " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
- done += temp;
- }
-
- do {
- if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
- LogError("Error in poll(POLLIN)");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
- ssize_t temp = TEMP_FAILURE_RETRY(read(sock.Get(), buffer, 2048));
- if (-1 == temp) {
- int err = errno;
- LogError("Error in read: " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- if (0 == temp) {
- LogError("Read return 0/Connection closed by server(?)");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- RawBuffer raw(buffer, buffer+temp);
- recv.Push(raw);
- } while(!recv.Ready());
- return SECURITY_SERVER_API_SUCCESS;
-}
-
-int sendToServerAncData(char const * const interface, const RawBuffer &send, struct msghdr &hdr) {
- int ret;
- SockRAII sock;
- ssize_t done = 0;
-
- if (SECURITY_SERVER_API_SUCCESS != (ret = sock.Connect(interface))) {
- LogError("Error in SockRAII");
- return ret;
- }
-
- while ((send.size() - done) > 0) {
- if (0 >= waitForSocket(sock.Get(), POLLOUT, POLL_TIMEOUT)) {
- LogError("Error in poll(POLLOUT)");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
- ssize_t temp = TEMP_FAILURE_RETRY(write(sock.Get(), &send[done], send.size() - done));
- if (-1 == temp) {
- int err = errno;
- LogError("Error in write: " << strerror(err));
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
- done += temp;
- }
-
- if (0 >= waitForSocket(sock.Get(), POLLIN, POLL_TIMEOUT)) {
- LogError("Error in poll(POLLIN)");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- ssize_t temp = TEMP_FAILURE_RETRY(recvmsg(sock.Get(), &hdr, MSG_CMSG_CLOEXEC));
-
- if (temp < 0) {
- int err = errno;
- LogError("Error in recvmsg(): " << strerror(err) << " errno: " << err);
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- if (0 == temp) {
- LogError("Read return 0/Connection closed by server(?)");
- return SECURITY_SERVER_API_ERROR_SOCKET;
- }
-
- return SECURITY_SERVER_API_SUCCESS;
-}
-
-int try_catch(const std::function<int()>& func)
-{
- try {
- return func();
- } catch (MessageBuffer::Exception::Base &e) {
- LogError("SecurityServer::MessageBuffer::Exception " << e.DumpToString());
- } catch (std::exception &e) {
- LogError("STD exception " << e.what());
- } catch (...) {
- LogError("Unknown exception occured");
- }
- return SECURITY_SERVER_API_ERROR_UNKNOWN;
-}
-
-} // namespace SecurityServer
-
-static void init_lib(void) __attribute__ ((constructor));
-static void init_lib(void)
-{
- securityClientEnableLogSystem();
-}
-
-static void fini_lib(void) __attribute__ ((destructor));
-static void fini_lib(void)
-{
-
-}
-
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * 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 ServerConnectionErrorException.h
+ * @author Lukasz Wojciechowski <l.wojciechow@partner.samsung.com>
+ * @version 1.0
+ * @brief Implementation of ServerConnectionErrorException
+ */
+
+#ifndef SRC_COMMON_EXCEPTIONS_SERVERCONNECTIONERROREXCEPTION_H_
+#define SRC_COMMON_EXCEPTIONS_SERVERCONNECTIONERROREXCEPTION_H_
+
+#include "Exception.h"
+
+#include <exception>
+
+namespace Cynara {
+
+class ServerConnectionErrorException : public Exception {
+public:
+ ServerConnectionErrorException() = default;
+ virtual ~ServerConnectionErrorException() = default;
+ virtual const char* what() const noexcept {
+ return "ServerConnectionError";
+ }
+};
+
+} /* namespace Cynara */
+
+#endif /* SRC_COMMON_EXCEPTIONS_SERVERCONNECTIONERROREXCEPTION_H_ */